diff --git a/examplesForWebDemo/src/html5/floatingText/hello.js b/examplesForWebDemo/src/html5/floatingText/hello.js index bb40ff1059c..79dfcec9f3e 100644 --- a/examplesForWebDemo/src/html5/floatingText/hello.js +++ b/examplesForWebDemo/src/html5/floatingText/hello.js @@ -5,7 +5,7 @@ this.$relY = 0.4 + 0.2 * Math.random(); this.$relXVelocity = this.randomVelocity(); this.$relYVelocity = this.randomVelocity(); - this.$message = 'Hello Kotlin'; + this.$message = 'Hello, Kotlin!'; this.$textHeightInPixels = 60; { hello.get_context().font = 'bold ' + this.get_textHeightInPixels() + 'px Georgia, serif'; diff --git a/examplesForWebDemo/src/html5/floatingText/test.kt b/examplesForWebDemo/src/html5/floatingText/test.kt index 06e9afb5229..e5bca3ea4d9 100644 --- a/examplesForWebDemo/src/html5/floatingText/test.kt +++ b/examplesForWebDemo/src/html5/floatingText/test.kt @@ -25,7 +25,7 @@ class HelloKotlin() { var relYVelocity = randomVelocity() - val message = "Hello Kotlin" + val message = "Hello, Kotlin!" val textHeightInPixels = 60 { context.font = "bold ${textHeightInPixels}px Georgia, serif" diff --git a/translator/src/org/jetbrains/k2js/translate/expression/ExpressionVisitor.java b/translator/src/org/jetbrains/k2js/translate/expression/ExpressionVisitor.java index b51d6bf5243..fc6c62c44a9 100644 --- a/translator/src/org/jetbrains/k2js/translate/expression/ExpressionVisitor.java +++ b/translator/src/org/jetbrains/k2js/translate/expression/ExpressionVisitor.java @@ -132,7 +132,7 @@ public final class ExpressionVisitor extends TranslatorVisitor { @NotNull public JsNode visitCallExpression(@NotNull JetCallExpression expression, @NotNull TranslationContext context) { - return CallTranslator.translate(expression, null, CallType.NORMAL, context); + return CallExpressionTranslator.translate(expression, null, CallType.NORMAL, context); } @Override diff --git a/translator/src/org/jetbrains/k2js/translate/expression/ForTranslator.java b/translator/src/org/jetbrains/k2js/translate/expression/ForTranslator.java index 6ea2cbe90b4..7d8522cadfd 100644 --- a/translator/src/org/jetbrains/k2js/translate/expression/ForTranslator.java +++ b/translator/src/org/jetbrains/k2js/translate/expression/ForTranslator.java @@ -3,6 +3,7 @@ package org.jetbrains.k2js.translate.expression; import com.google.dart.compiler.backend.js.ast.*; import com.google.dart.compiler.util.AstUtil; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.descriptors.CallableDescriptor; import org.jetbrains.jet.lang.descriptors.FunctionDescriptor; import org.jetbrains.jet.lang.psi.JetExpression; @@ -12,8 +13,7 @@ import org.jetbrains.k2js.translate.context.TemporaryVariable; import org.jetbrains.k2js.translate.context.TranslationContext; import org.jetbrains.k2js.translate.general.AbstractTranslator; import org.jetbrains.k2js.translate.general.Translation; -import org.jetbrains.k2js.translate.reference.CallTranslator; -import org.jetbrains.k2js.translate.reference.CallType; +import org.jetbrains.k2js.translate.reference.CallBuilder; import static org.jetbrains.k2js.translate.utils.BindingUtils.*; import static org.jetbrains.k2js.translate.utils.PsiUtils.getLoopBody; @@ -67,13 +67,13 @@ public final class ForTranslator extends AbstractTranslator { @NotNull private JsExpression nextMethodInvocation(@NotNull TemporaryVariable iterator) { FunctionDescriptor nextFunction = getNextFunction(context().bindingContext(), getLoopRange()); - return CallTranslator.translate(iterator.nameReference(), nextFunction, CallType.NORMAL, context()); + return translateMethodInvocation(iterator.nameReference(), nextFunction); } @NotNull private JsExpression hasNextMethodInvocation(@NotNull TemporaryVariable iterator) { CallableDescriptor hasNextFunction = getHasNextCallable(context().bindingContext(), getLoopRange()); - return CallTranslator.translate(iterator.nameReference(), hasNextFunction, CallType.NORMAL, context()); + return translateMethodInvocation(iterator.nameReference(), hasNextFunction); } @NotNull @@ -81,7 +81,7 @@ public final class ForTranslator extends AbstractTranslator { JetExpression rangeExpression = getLoopRange(); JsExpression range = Translation.translateAsExpression(rangeExpression, context()); FunctionDescriptor iteratorFunction = getIteratorFunction(context().bindingContext(), rangeExpression); - return CallTranslator.translate(range, iteratorFunction, CallType.NORMAL, context()); + return translateMethodInvocation(range, iteratorFunction); } @NotNull @@ -90,4 +90,13 @@ public final class ForTranslator extends AbstractTranslator { assert rangeExpression != null; return rangeExpression; } + + @NotNull + private JsExpression translateMethodInvocation(@Nullable JsExpression receiver, + @NotNull CallableDescriptor descriptor) { + return CallBuilder.build(context()) + .receiver(receiver) + .descriptor(descriptor) + .translate(); + } } diff --git a/translator/src/org/jetbrains/k2js/translate/operation/BinaryOperationTranslator.java b/translator/src/org/jetbrains/k2js/translate/operation/BinaryOperationTranslator.java index f1c3c98e315..21df9ae95b5 100644 --- a/translator/src/org/jetbrains/k2js/translate/operation/BinaryOperationTranslator.java +++ b/translator/src/org/jetbrains/k2js/translate/operation/BinaryOperationTranslator.java @@ -7,21 +7,25 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.descriptors.FunctionDescriptor; import org.jetbrains.jet.lang.psi.JetBinaryExpression; +import org.jetbrains.jet.lang.resolve.calls.ResolvedCall; import org.jetbrains.jet.lang.types.expressions.OperatorConventions; import org.jetbrains.jet.lexer.JetToken; import org.jetbrains.jet.lexer.JetTokens; import org.jetbrains.k2js.translate.context.TranslationContext; import org.jetbrains.k2js.translate.general.AbstractTranslator; import org.jetbrains.k2js.translate.intrinsic.EqualsIntrinsic; -import org.jetbrains.k2js.translate.reference.CallTranslator; +import org.jetbrains.k2js.translate.reference.CallBuilder; +import org.jetbrains.k2js.translate.reference.CallType; import java.util.Arrays; +import static com.google.dart.compiler.util.AstUtil.not; import static org.jetbrains.k2js.translate.operation.AssignmentTranslator.isAssignmentOperator; import static org.jetbrains.k2js.translate.operation.CompareToTranslator.isCompareToCall; import static org.jetbrains.k2js.translate.utils.BindingUtils.getFunctionDescriptorForOperationExpression; +import static org.jetbrains.k2js.translate.utils.BindingUtils.getResolvedCall; import static org.jetbrains.k2js.translate.utils.DescriptorUtils.isEquals; -import static org.jetbrains.k2js.translate.utils.PsiUtils.getOperationToken; +import static org.jetbrains.k2js.translate.utils.PsiUtils.*; import static org.jetbrains.k2js.translate.utils.TranslationUtils.translateLeftExpression; import static org.jetbrains.k2js.translate.utils.TranslationUtils.translateRightExpression; @@ -37,6 +41,12 @@ public final class BinaryOperationTranslator extends AbstractTranslator { return (new BinaryOperationTranslator(expression, context).translate()); } + @NotNull + /*package*/ static JsExpression translateAsOverloadedCall(@NotNull JetBinaryExpression expression, + @NotNull TranslationContext context) { + return (new BinaryOperationTranslator(expression, context)).translateAsOverloadedBinaryOperation(); + } + @NotNull private final JetBinaryExpression expression; @@ -67,7 +77,7 @@ public final class BinaryOperationTranslator extends AbstractTranslator { if (isEquals(operationDescriptor)) { return translateAsEqualsCall(); } - return CallTranslator.translate(expression, context()); + return translateAsOverloadedBinaryOperation(); } private boolean isNotOverloadable() { @@ -94,4 +104,38 @@ public final class BinaryOperationTranslator extends AbstractTranslator { return new JsBinaryOperation(operator, left, right); } + + @NotNull + private JsExpression translateAsOverloadedBinaryOperation() { + CallBuilder callBuilder = setReceiverAndArguments(); + ResolvedCall resolvedCall1 = + getResolvedCall(context().bindingContext(), expression.getOperationReference()); + JsExpression result = callBuilder.resolvedCall(resolvedCall1) + .type(CallType.NORMAL).translate(); + return mayBeWrapWithNegation(result); + } + + @NotNull + private CallBuilder setReceiverAndArguments() { + CallBuilder callBuilder = CallBuilder.build(context()); + + JsExpression leftExpression = translateLeftExpression(context(), expression); + JsExpression rightExpression = translateRightExpression(context(), expression); + + if (isInOrNotInOperation(expression)) { + return callBuilder.receiver(rightExpression).args(leftExpression); + } else { + return callBuilder.receiver(leftExpression).args(rightExpression); + } + } + + @NotNull + private JsExpression mayBeWrapWithNegation(@NotNull JsExpression result) { + if (isNotInOperation(expression)) { + return not(result); + } else { + return result; + } + } + } diff --git a/translator/src/org/jetbrains/k2js/translate/operation/CompareToTranslator.java b/translator/src/org/jetbrains/k2js/translate/operation/CompareToTranslator.java index 60773d42b3d..c9a40343684 100644 --- a/translator/src/org/jetbrains/k2js/translate/operation/CompareToTranslator.java +++ b/translator/src/org/jetbrains/k2js/translate/operation/CompareToTranslator.java @@ -11,7 +11,6 @@ import org.jetbrains.jet.lexer.JetToken; import org.jetbrains.k2js.translate.context.TranslationContext; import org.jetbrains.k2js.translate.general.AbstractTranslator; import org.jetbrains.k2js.translate.intrinsic.CompareToIntrinsic; -import org.jetbrains.k2js.translate.reference.CallTranslator; import org.jetbrains.k2js.translate.utils.TranslationUtils; import java.util.Arrays; @@ -70,7 +69,7 @@ public final class CompareToTranslator extends AbstractTranslator { @NotNull private JsExpression overloadedCompareTo() { JsBinaryOperator correspondingOperator = OperatorTable.getBinaryOperator(getOperationToken(expression)); - JsExpression methodCall = CallTranslator.translate(expression, context()); + JsExpression methodCall = BinaryOperationTranslator.translateAsOverloadedCall(expression, context()); return new JsBinaryOperation(correspondingOperator, methodCall, TranslationUtils.zeroLiteral(context())); } diff --git a/translator/src/org/jetbrains/k2js/translate/operation/UnaryOperationTranslator.java b/translator/src/org/jetbrains/k2js/translate/operation/UnaryOperationTranslator.java index 02d888a79e7..51fdf4eb571 100644 --- a/translator/src/org/jetbrains/k2js/translate/operation/UnaryOperationTranslator.java +++ b/translator/src/org/jetbrains/k2js/translate/operation/UnaryOperationTranslator.java @@ -4,7 +4,13 @@ import com.google.dart.compiler.backend.js.ast.JsExpression; import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.lang.psi.JetUnaryExpression; import org.jetbrains.k2js.translate.context.TranslationContext; -import org.jetbrains.k2js.translate.reference.CallTranslator; +import org.jetbrains.k2js.translate.reference.CallBuilder; +import org.jetbrains.k2js.translate.reference.CallType; +import org.jetbrains.k2js.translate.utils.TranslationUtils; + +import java.util.Collections; + +import static org.jetbrains.k2js.translate.utils.BindingUtils.getResolvedCall; /** * @author Pavel Talanov @@ -18,6 +24,16 @@ public final class UnaryOperationTranslator { if (IncrementTranslator.isIncrement(expression)) { return IncrementTranslator.translate(expression, context); } - return CallTranslator.translate(expression, context); + return translateAsCall(expression, context); + } + + @NotNull + private static JsExpression translateAsCall(@NotNull JetUnaryExpression expression, + @NotNull TranslationContext context) { + return CallBuilder.build(context) + .receiver(TranslationUtils.translateBaseExpression(context, expression)) + .args(Collections.emptyList()) + .resolvedCall(getResolvedCall(context.bindingContext(), expression.getOperationReference())) + .type(CallType.NORMAL).translate(); } } diff --git a/translator/src/org/jetbrains/k2js/translate/reference/CallBuilder.java b/translator/src/org/jetbrains/k2js/translate/reference/CallBuilder.java new file mode 100644 index 00000000000..03b2d2c0d16 --- /dev/null +++ b/translator/src/org/jetbrains/k2js/translate/reference/CallBuilder.java @@ -0,0 +1,192 @@ +package org.jetbrains.k2js.translate.reference; + +import com.google.common.collect.Lists; +import com.google.dart.compiler.backend.js.ast.JsExpression; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.jet.lang.descriptors.CallableDescriptor; +import org.jetbrains.jet.lang.resolve.calls.ResolvedCall; +import org.jetbrains.jet.lang.resolve.calls.ResolvedCallImpl; +import org.jetbrains.k2js.translate.context.TranslationContext; + +import java.util.Arrays; +import java.util.List; + +/** + * @author Pavel Talanov + */ +public final class CallBuilder { + + public static CallBuilder build(@NotNull TranslationContext context) { + return new CallBuilder(context); + } + + @NotNull + private final TranslationContext context; + @Nullable + private /*var*/ JsExpression receiver = null; + @NotNull + private final List args = Lists.newArrayList(); + @NotNull + private /*var*/ CallType callType = CallType.NORMAL; + @Nullable + private /*var*/ ResolvedCall resolvedCall = null; + @Nullable + private /*var*/ CallableDescriptor descriptor = null; + @Nullable + private /*var*/ JsExpression callee = null; + + + private CallBuilder(@NotNull TranslationContext context) { + this.context = context; + } + + @NotNull + public CallBuilder receiver(@Nullable JsExpression receiver) { + this.receiver = receiver; + return this; + } + + @NotNull + public CallBuilder args(@NotNull List args) { + assert this.args.isEmpty(); + this.args.addAll(args); + return this; + } + + @NotNull + public CallBuilder args(@NotNull JsExpression... args) { + return args(Arrays.asList(args)); + } + + @NotNull + public CallBuilder descriptor(@NotNull CallableDescriptor descriptor) { + this.descriptor = descriptor; + return this; + } + + @NotNull + public CallBuilder callee(@Nullable JsExpression callee) { + this.callee = callee; + return this; + } + + @NotNull + public CallBuilder resolvedCall(@NotNull ResolvedCall call) { + this.resolvedCall = call; + return this; + } + + @NotNull + public CallBuilder type(@NotNull CallType type) { + this.callType = type; + return this; + } + + //TODO: must be private + @NotNull + public CallTranslator finish() { + if (resolvedCall == null) { + assert descriptor != null; + resolvedCall = ResolvedCallImpl.create(descriptor); + } + if (descriptor == null) { + descriptor = resolvedCall.getCandidateDescriptor().getOriginal(); + } + assert resolvedCall != null; + return new CallTranslator(receiver, callee, args, resolvedCall, descriptor, callType, context); + } + + @NotNull + public JsExpression translate() { + return finish().translate(); + } + /* + @NotNull + private CallTranslator buildFromUnary(@NotNull JetUnaryExpression unaryExpression) { + JsExpression receiver = TranslationUtils.translateBaseExpression(context, unaryExpression); + List arguments = Collections.emptyList(); + ResolvedCall resolvedCall = + getResolvedCall(context.bindingContext(), unaryExpression.getOperationReference()); + return new CallTranslator(receiver, null, arguments, resolvedCall, null, CallType.NORMAL, context); + } + + //TODO: method too long + @NotNull + private CallTranslator buildFromBinary(@NotNull JetBinaryExpression binaryExpression, + boolean swapReceiverAndArgument) { + + JsExpression leftExpression = translateLeftExpression(context, binaryExpression); + JsExpression rightExpression = translateRightExpression(context, binaryExpression); + + JsExpression receiver; + List arguments; + if (swapReceiverAndArgument) { + receiver = rightExpression; + arguments = Arrays.asList(leftExpression); + } else { + receiver = leftExpression; + arguments = Arrays.asList(rightExpression); + } + + ResolvedCall resolvedCall = + getResolvedCall(context.bindingContext(), binaryExpression.getOperationReference()); + return new CallTranslator(receiver, null, arguments, resolvedCall, null, CallType.NORMAL, context); + } + + @NotNull + private CallTranslator buildFromCallExpression(@NotNull JetCallExpression callExpression, + @Nullable JsExpression receiver, + @NotNull CallType callType) { + ResolvedCall resolvedCall = getResolvedCallForCallExpression(context.bindingContext(), callExpression); + List arguments = translateArgumentsForCallExpression(callExpression, context); + JsExpression callee = null; + if (resolvedCall.getCandidateDescriptor() instanceof ExpressionAsFunctionDescriptor) { + callee = Translation.translateAsExpression(getCallee(callExpression), context); + } + return new CallTranslator(receiver, callee, arguments, resolvedCall, null, callType, context); + } + + @NotNull + private List translateArgumentsForCallExpression(@NotNull JetCallExpression callExpression, + @NotNull TranslationContext context) { + List result = new ArrayList(); + ResolvedCall resolvedCall = getResolvedCallForCallExpression(context.bindingContext(), callExpression); + Map formalToActualArguments = resolvedCall.getValueArguments(); + for (ValueParameterDescriptor parameterDescriptor : resolvedCall.getResultingDescriptor().getValueParameters()) { + ResolvedValueArgument actualArgument = formalToActualArguments.get(parameterDescriptor); + result.add(translateSingleArgument(actualArgument, parameterDescriptor)); + } + return result; + } + + + //TODO: refactor + @NotNull + private JsExpression translateSingleArgument(@NotNull ResolvedValueArgument actualArgument, + @NotNull ValueParameterDescriptor parameterDescriptor) { + List argumentExpressions = actualArgument.getArgumentExpressions(); + if (actualArgument instanceof VarargValueArgument) { + return translateVarargArgument(argumentExpressions); + } + if (actualArgument instanceof DefaultValueArgument) { + JetExpression defaultArgument = getDefaultArgument(context.bindingContext(), parameterDescriptor); + return Translation.translateAsExpression(defaultArgument, context); + } + assert actualArgument instanceof ExpressionValueArgument; + assert argumentExpressions.size() == 1; + return Translation.translateAsExpression(argumentExpressions.get(0), context); + } + + @NotNull + private JsExpression translateVarargArgument(@NotNull List arguments) { + JsArrayLiteral varargArgument = new JsArrayLiteral(); + for (JetExpression argument : arguments) { + varargArgument.getExpressions().add(Translation.translateAsExpression(argument, context)); + } + return varargArgument; + } + */ + + +} diff --git a/translator/src/org/jetbrains/k2js/translate/reference/CallExpressionTranslator.java b/translator/src/org/jetbrains/k2js/translate/reference/CallExpressionTranslator.java new file mode 100644 index 00000000000..428382b0b21 --- /dev/null +++ b/translator/src/org/jetbrains/k2js/translate/reference/CallExpressionTranslator.java @@ -0,0 +1,102 @@ +package org.jetbrains.k2js.translate.reference; + +import com.google.dart.compiler.backend.js.ast.JsArrayLiteral; +import com.google.dart.compiler.backend.js.ast.JsExpression; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor; +import org.jetbrains.jet.lang.psi.JetCallExpression; +import org.jetbrains.jet.lang.psi.JetExpression; +import org.jetbrains.jet.lang.resolve.calls.*; +import org.jetbrains.k2js.translate.context.TranslationContext; +import org.jetbrains.k2js.translate.general.AbstractTranslator; +import org.jetbrains.k2js.translate.general.Translation; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import static org.jetbrains.k2js.translate.utils.BindingUtils.getDefaultArgument; +import static org.jetbrains.k2js.translate.utils.BindingUtils.getResolvedCallForCallExpression; +import static org.jetbrains.k2js.translate.utils.PsiUtils.getCallee; + +/** + * @author Pavel Talanov + */ +public final class CallExpressionTranslator extends AbstractTranslator { + + @NotNull + public static JsExpression translate(@NotNull JetCallExpression expression, + @Nullable JsExpression receiver, + @NotNull CallType callType, + @NotNull TranslationContext context) { + return (new CallExpressionTranslator(expression, context)).translate(receiver, callType); + } + + @NotNull + private final JetCallExpression expression; + + private CallExpressionTranslator(@NotNull JetCallExpression expression, + @NotNull TranslationContext context) { + super(context); + this.expression = expression; + } + + @NotNull + private JsExpression translate(@Nullable JsExpression receiver, + @NotNull CallType callType) { + ResolvedCall resolvedCall = getResolvedCallForCallExpression(context().bindingContext(), expression); + return CallBuilder.build(context()) + .receiver(receiver) + .callee(getCalleeExpression(resolvedCall)) + .args(translateArguments()) + .resolvedCall(resolvedCall) + .type(callType) + .translate(); + } + + @Nullable + private JsExpression getCalleeExpression(@NotNull ResolvedCall resolvedCall) { + if (resolvedCall.getCandidateDescriptor() instanceof ExpressionAsFunctionDescriptor) { + return Translation.translateAsExpression(getCallee(expression), context()); + } + return null; + } + + @NotNull + private List translateArguments() { + List result = new ArrayList(); + ResolvedCall resolvedCall = getResolvedCallForCallExpression(context().bindingContext(), expression); + Map formalToActualArguments = resolvedCall.getValueArguments(); + for (ValueParameterDescriptor parameterDescriptor : resolvedCall.getResultingDescriptor().getValueParameters()) { + ResolvedValueArgument actualArgument = formalToActualArguments.get(parameterDescriptor); + result.add(translateSingleArgument(actualArgument, parameterDescriptor)); + } + return result; + } + + @NotNull + private JsExpression translateSingleArgument(@NotNull ResolvedValueArgument actualArgument, + @NotNull ValueParameterDescriptor parameterDescriptor) { + List argumentExpressions = actualArgument.getArgumentExpressions(); + if (actualArgument instanceof VarargValueArgument) { + return translateVarargArgument(argumentExpressions); + } + if (actualArgument instanceof DefaultValueArgument) { + JetExpression defaultArgument = getDefaultArgument(context().bindingContext(), parameterDescriptor); + return Translation.translateAsExpression(defaultArgument, context()); + } + assert actualArgument instanceof ExpressionValueArgument; + assert argumentExpressions.size() == 1; + return Translation.translateAsExpression(argumentExpressions.get(0), context()); + } + + @NotNull + private JsExpression translateVarargArgument(@NotNull List arguments) { + JsArrayLiteral varargArgument = new JsArrayLiteral(); + for (JetExpression argument : arguments) { + varargArgument.getExpressions().add(Translation.translateAsExpression(argument, context())); + } + return varargArgument; + } +} diff --git a/translator/src/org/jetbrains/k2js/translate/reference/CallTranslator.java b/translator/src/org/jetbrains/k2js/translate/reference/CallTranslator.java index 07bdc8f8b66..fe2e2f9f9c5 100644 --- a/translator/src/org/jetbrains/k2js/translate/reference/CallTranslator.java +++ b/translator/src/org/jetbrains/k2js/translate/reference/CallTranslator.java @@ -1,35 +1,32 @@ package org.jetbrains.k2js.translate.reference; -import com.google.dart.compiler.backend.js.ast.*; +import com.google.dart.compiler.backend.js.ast.JsExpression; +import com.google.dart.compiler.backend.js.ast.JsInvocation; +import com.google.dart.compiler.backend.js.ast.JsNameRef; +import com.google.dart.compiler.backend.js.ast.JsNew; import com.google.dart.compiler.util.AstUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.descriptors.*; -import org.jetbrains.jet.lang.psi.JetBinaryExpression; -import org.jetbrains.jet.lang.psi.JetCallExpression; -import org.jetbrains.jet.lang.psi.JetExpression; -import org.jetbrains.jet.lang.psi.JetUnaryExpression; -import org.jetbrains.jet.lang.resolve.calls.*; +import org.jetbrains.jet.lang.resolve.calls.ExpressionAsFunctionDescriptor; +import org.jetbrains.jet.lang.resolve.calls.ResolvedCall; import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor; import org.jetbrains.k2js.translate.context.TranslationContext; import org.jetbrains.k2js.translate.general.AbstractTranslator; -import org.jetbrains.k2js.translate.general.Translation; import org.jetbrains.k2js.translate.intrinsic.FunctionIntrinsic; import org.jetbrains.k2js.translate.utils.TranslationUtils; -import java.util.*; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; -import static com.google.dart.compiler.util.AstUtil.not; -import static org.jetbrains.k2js.translate.utils.BindingUtils.*; import static org.jetbrains.k2js.translate.utils.DescriptorUtils.*; -import static org.jetbrains.k2js.translate.utils.PsiUtils.*; -import static org.jetbrains.k2js.translate.utils.TranslationUtils.*; +import static org.jetbrains.k2js.translate.utils.TranslationUtils.getThisObject; /** * @author Pavel Talanov */ //TODO: write tests on calling backing fields as functions -//TODO: constructor receives too many parameters //TODO: reorder methods properly public final class CallTranslator extends AbstractTranslator { @@ -46,110 +43,6 @@ public final class CallTranslator extends AbstractTranslator { public /*var*/ JsExpression functionReference; } - private static final class Builder { - - @NotNull - private final TranslationContext context; - - private Builder(@NotNull TranslationContext context) { - this.context = context; - } - - @NotNull - private CallTranslator buildFromUnary(@NotNull JetUnaryExpression unaryExpression) { - JsExpression receiver = TranslationUtils.translateBaseExpression(context, unaryExpression); - List arguments = Collections.emptyList(); - ResolvedCall resolvedCall = - getResolvedCall(context.bindingContext(), unaryExpression.getOperationReference()); - return new CallTranslator(receiver, null, arguments, resolvedCall, null, CallType.NORMAL, context); - } - - //TODO: method too long - @NotNull - private CallTranslator buildFromBinary(@NotNull JetBinaryExpression binaryExpression, - boolean swapReceiverAndArgument) { - - JsExpression leftExpression = translateLeftExpression(context, binaryExpression); - JsExpression rightExpression = translateRightExpression(context, binaryExpression); - - JsExpression receiver; - List arguments; - if (swapReceiverAndArgument) { - receiver = rightExpression; - arguments = Arrays.asList(leftExpression); - } else { - receiver = leftExpression; - arguments = Arrays.asList(rightExpression); - } - - ResolvedCall resolvedCall = - getResolvedCall(context.bindingContext(), binaryExpression.getOperationReference()); - return new CallTranslator(receiver, null, arguments, resolvedCall, null, CallType.NORMAL, context); - } - - @NotNull - private CallTranslator buildFromCallExpression(@NotNull JetCallExpression callExpression, - @Nullable JsExpression receiver, - @NotNull CallType callType) { - ResolvedCall resolvedCall = getResolvedCallForCallExpression(context.bindingContext(), callExpression); - List arguments = translateArgumentsForCallExpression(callExpression, context); - JsExpression callee = null; - if (resolvedCall.getCandidateDescriptor() instanceof ExpressionAsFunctionDescriptor) { - callee = Translation.translateAsExpression(getCallee(callExpression), context); - } - return new CallTranslator(receiver, callee, arguments, resolvedCall, null, callType, context); - } - - @NotNull - private List translateArgumentsForCallExpression(@NotNull JetCallExpression callExpression, - @NotNull TranslationContext context) { - List result = new ArrayList(); - ResolvedCall resolvedCall = getResolvedCallForCallExpression(context.bindingContext(), callExpression); - Map formalToActualArguments = resolvedCall.getValueArguments(); - for (ValueParameterDescriptor parameterDescriptor : resolvedCall.getResultingDescriptor().getValueParameters()) { - ResolvedValueArgument actualArgument = formalToActualArguments.get(parameterDescriptor); - result.add(translateSingleArgument(actualArgument, parameterDescriptor)); - } - return result; - } - - - //TODO: refactor - @NotNull - private JsExpression translateSingleArgument(@NotNull ResolvedValueArgument actualArgument, - @NotNull ValueParameterDescriptor parameterDescriptor) { - List argumentExpressions = actualArgument.getArgumentExpressions(); - if (actualArgument instanceof VarargValueArgument) { - return translateVarargArgument(argumentExpressions); - } - if (actualArgument instanceof DefaultValueArgument) { - JetExpression defaultArgument = getDefaultArgument(context.bindingContext(), parameterDescriptor); - return Translation.translateAsExpression(defaultArgument, context); - } - assert actualArgument instanceof ExpressionValueArgument; - assert argumentExpressions.size() == 1; - return Translation.translateAsExpression(argumentExpressions.get(0), context); - } - - @NotNull - private JsExpression translateVarargArgument(@NotNull List arguments) { - JsArrayLiteral varargArgument = new JsArrayLiteral(); - for (JetExpression argument : arguments) { - varargArgument.getExpressions().add(Translation.translateAsExpression(argument, context)); - } - return varargArgument; - } - } - - @NotNull - public static JsExpression translate(@Nullable JsExpression receiver, - @NotNull CallableDescriptor descriptor, - @NotNull CallType callType, - @NotNull TranslationContext context) { - return translate(receiver, Collections.emptyList(), - ResolvedCallImpl.create(descriptor), null, callType, context); - } - @NotNull public static JsExpression translate(@Nullable JsExpression receiver, @NotNull ResolvedCall resolvedCall, @@ -169,41 +62,6 @@ public final class CallTranslator extends AbstractTranslator { return (new CallTranslator(receiver, null, arguments, resolvedCall, descriptorToCall, callType, context)).translate(); } - @NotNull - public static JsExpression translate(@NotNull JetUnaryExpression unaryExpression, - @NotNull TranslationContext context) { - return (new Builder(context).buildFromUnary(unaryExpression)).translate(); - } - - @NotNull - public static JsExpression translate(@NotNull JetCallExpression callExpression, - @Nullable JsExpression receiver, - @NotNull CallType callType, - @NotNull TranslationContext context) { - return (new Builder(context).buildFromCallExpression(callExpression, receiver, callType)).translate(); - } - - @NotNull - public static JsExpression translate(@NotNull JetBinaryExpression binaryExpression, - @NotNull TranslationContext context) { - boolean shouldSwapReceiverAndArgument = isInOrNotInOperation(binaryExpression); - JsExpression result = (new Builder(context)) - .buildFromBinary(binaryExpression, shouldSwapReceiverAndArgument).translate(); - if (isInOrNotInOperation(binaryExpression)) { - return mayBeWrapWithNegation(result, isNotInOperation(binaryExpression)); - } - return result; - } - - @NotNull - private static JsExpression mayBeWrapWithNegation(@NotNull JsExpression expression, boolean shouldWrap) { - if (shouldWrap) { - return not(expression); - } else { - return expression; - } - } - @Nullable private /*var*/ JsExpression receiver; @@ -222,27 +80,23 @@ public final class CallTranslator extends AbstractTranslator { @NotNull private final CallType callType; - private CallTranslator(@Nullable JsExpression receiver, @Nullable JsExpression callee, - @NotNull List arguments, - @NotNull ResolvedCall resolvedCall, - @Nullable CallableDescriptor descriptorToCall, - @NotNull CallType callType, - @NotNull TranslationContext context) { + /*package*/ CallTranslator(@Nullable JsExpression receiver, @Nullable JsExpression callee, + @NotNull List arguments, + @NotNull ResolvedCall resolvedCall, + @NotNull CallableDescriptor descriptorToCall, + @NotNull CallType callType, + @NotNull TranslationContext context) { super(context); this.receiver = receiver; this.arguments = arguments; this.resolvedCall = resolvedCall; this.callType = callType; - if (descriptorToCall != null) { - this.descriptor = descriptorToCall; - } else { - this.descriptor = resolvedCall.getCandidateDescriptor().getOriginal(); - } + this.descriptor = descriptorToCall; this.callee = callee; } @NotNull - private JsExpression translate() { + /*package*/ JsExpression translate() { if (isIntrinsic()) { return intrinsicInvocation(); } diff --git a/translator/src/org/jetbrains/k2js/translate/reference/QualifiedExpressionTranslator.java b/translator/src/org/jetbrains/k2js/translate/reference/QualifiedExpressionTranslator.java index 38b577b126b..ae2f3e6d351 100644 --- a/translator/src/org/jetbrains/k2js/translate/reference/QualifiedExpressionTranslator.java +++ b/translator/src/org/jetbrains/k2js/translate/reference/QualifiedExpressionTranslator.java @@ -52,7 +52,7 @@ public final class QualifiedExpressionTranslator { ((JetSimpleNameExpression) selector, receiver, callType, context); } if (selector instanceof JetCallExpression) { - return CallTranslator.translate((JetCallExpression) selector, receiver, callType, context); + return CallExpressionTranslator.translate((JetCallExpression) selector, receiver, callType, context); } throw new AssertionError("Unexpected qualified expression"); }