diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/intrinsic/functions/factories/TopLevelFIF.java b/js/js.translator/src/org/jetbrains/k2js/translate/intrinsic/functions/factories/TopLevelFIF.java index e585904e60f..90e3c665de8 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/intrinsic/functions/factories/TopLevelFIF.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/intrinsic/functions/factories/TopLevelFIF.java @@ -19,9 +19,7 @@ package org.jetbrains.k2js.translate.intrinsic.functions.factories; import com.google.dart.compiler.backend.js.ast.*; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.jetbrains.jet.lang.descriptors.CallableDescriptor; import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; -import org.jetbrains.jet.lang.descriptors.FunctionDescriptor; import org.jetbrains.jet.lang.descriptors.PropertyDescriptor; import org.jetbrains.jet.lang.psi.JetExpression; import org.jetbrains.jet.lang.psi.JetQualifiedExpression; @@ -31,12 +29,9 @@ import org.jetbrains.jet.lang.resolve.name.Name; import org.jetbrains.jet.lang.resolve.scopes.receivers.ExpressionReceiver; import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue; import org.jetbrains.jet.lang.types.JetType; -import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; import org.jetbrains.jet.lang.types.lang.PrimitiveType; -import org.jetbrains.k2js.translate.context.Namer; import org.jetbrains.k2js.translate.context.TranslationContext; import org.jetbrains.k2js.translate.intrinsic.functions.basic.FunctionIntrinsic; -import org.jetbrains.k2js.translate.intrinsic.functions.patterns.DescriptorPredicate; import org.jetbrains.k2js.translate.intrinsic.functions.patterns.NamePredicate; import org.jetbrains.k2js.translate.reference.CallTranslator; import org.jetbrains.k2js.translate.utils.AnnotationsUtils; @@ -47,7 +42,6 @@ import java.util.List; import static org.jetbrains.k2js.translate.intrinsic.functions.basic.FunctionIntrinsic.CallParametersAwareFunctionIntrinsic; import static org.jetbrains.k2js.translate.intrinsic.functions.patterns.PatternBuilder.pattern; -import static org.jetbrains.k2js.translate.utils.TranslationUtils.generateInvocationArguments; public final class TopLevelFIF extends CompositeFIF { @NotNull @@ -139,46 +133,6 @@ public final class TopLevelFIF extends CompositeFIF { add(pattern("String|Boolean|Char|Number.equals"), EQUALS); add(pattern("jet", "arrayOfNulls"), new KotlinFunctionIntrinsic("nullArray")); add(pattern("jet", "iterator").receiverExists(), RETURN_RECEIVER_INTRINSIC); - add(new DescriptorPredicate() { - @Override - public boolean apply(@NotNull FunctionDescriptor descriptor) { - if (!descriptor.getName().asString().equals("invoke")) { - return false; - } - int parameterCount = descriptor.getValueParameters().size(); - DeclarationDescriptor fun = descriptor.getContainingDeclaration(); - return fun == (descriptor.getReceiverParameter() == null - ? KotlinBuiltIns.getInstance().getFunction(parameterCount) - : KotlinBuiltIns.getInstance().getExtensionFunction(parameterCount)); - } - }, new CallParametersAwareFunctionIntrinsic() { - @NotNull - @Override - public JsExpression apply( - @NotNull CallTranslator callTranslator, - @NotNull List arguments, - @NotNull TranslationContext context - ) { - JsExpression thisExpression = callTranslator.getCallParameters().getThisObject(); - JsExpression functionReference = callTranslator.getCallParameters().getFunctionReference(); - if (thisExpression == null) { - return new JsInvocation(functionReference, arguments); - } - else if (callTranslator.getResolvedCall().getReceiverArgument().exists()) { - return callTranslator.extensionFunctionCall(false); - } - else { - CallableDescriptor descriptor = callTranslator.getResolvedCall().getCandidateDescriptor(); - if (descriptor.getName().asString().equals("invoke") && - functionReference instanceof JsNameRef && - ((JsNameRef) functionReference).getIdent().startsWith("invoke")) { - return callTranslator.explicitInvokeCall(); - } - return new JsInvocation(Namer.getFunctionCallRef(functionReference), generateInvocationArguments(thisExpression, arguments)); - } - } - } - ); add(pattern("jet", "Map", "get").checkOverridden(), NATIVE_MAP_GET); add(pattern("js", "set").receiverExists(), NATIVE_MAP_SET); diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/reference/AbstractCallExpressionTranslator.java b/js/js.translator/src/org/jetbrains/k2js/translate/reference/AbstractCallExpressionTranslator.java index a31778088b2..ea9b7a91a76 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/reference/AbstractCallExpressionTranslator.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/reference/AbstractCallExpressionTranslator.java @@ -19,6 +19,7 @@ package org.jetbrains.k2js.translate.reference; 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.FunctionDescriptor; import org.jetbrains.jet.lang.psi.JetCallExpression; import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall; import org.jetbrains.k2js.translate.context.TranslationContext; @@ -31,7 +32,7 @@ public abstract class AbstractCallExpressionTranslator extends AbstractTranslato @NotNull protected final JetCallExpression expression; @NotNull - protected final ResolvedCall resolvedCall; + protected final ResolvedCall resolvedCall; @Nullable protected final JsExpression receiver; @NotNull diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/reference/CallExpressionTranslator.java b/js/js.translator/src/org/jetbrains/k2js/translate/reference/CallExpressionTranslator.java index ed48e100bfa..ec505d28a4c 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/reference/CallExpressionTranslator.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/reference/CallExpressionTranslator.java @@ -17,23 +17,10 @@ package org.jetbrains.k2js.translate.reference; import com.google.dart.compiler.backend.js.ast.JsExpression; -import com.google.dart.compiler.backend.js.ast.JsName; -import com.google.dart.compiler.backend.js.ast.JsNameRef; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.jetbrains.jet.lang.descriptors.CallableDescriptor; import org.jetbrains.jet.lang.psi.JetCallExpression; -import org.jetbrains.jet.lang.psi.JetExpression; -import org.jetbrains.jet.lang.psi.JetSimpleNameExpression; -import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall; -import org.jetbrains.jet.lang.resolve.calls.model.VariableAsFunctionResolvedCall; -import org.jetbrains.jet.lang.resolve.calls.util.ExpressionAsFunctionDescriptor; import org.jetbrains.k2js.translate.context.TranslationContext; -import org.jetbrains.k2js.translate.general.Translation; -import org.jetbrains.k2js.translate.utils.AnnotationsUtils; -import org.jetbrains.k2js.translate.utils.PsiUtils; - -import static org.jetbrains.k2js.translate.utils.PsiUtils.getCallee; public final class CallExpressionTranslator extends AbstractCallExpressionTranslator { @@ -48,88 +35,14 @@ public final class CallExpressionTranslator extends AbstractCallExpressionTransl return (new CallExpressionTranslator(expression, receiver, callType, context)).translate(); } - private final boolean isNativeFunctionCall; - private CallArgumentTranslator.ArgumentsInfo argumentsInfo = null; - private JsExpression translatedReceiver = null; - private JsExpression translatedCallee = null; - private CallExpressionTranslator(@NotNull JetCallExpression expression, @Nullable JsExpression receiver, @NotNull CallType callType, @NotNull TranslationContext context) { super(expression, receiver, callType, context); - this.isNativeFunctionCall = AnnotationsUtils.isNativeObject(resolvedCall.getCandidateDescriptor()); } @NotNull private JsExpression translate() { - prepareToBuildCall(); - - return CallBuilder.build(context()) - .receiver(translatedReceiver) - .callee(translatedCallee) - .args(argumentsInfo.getTranslateArguments()) - .resolvedCall(getResolvedCall()) - .type(callType) - .translate(); + return ReferencePackage.buildCall(context(), resolvedCall, receiver); } - - private void prepareToBuildCall() { - argumentsInfo = CallArgumentTranslator.translate(resolvedCall, receiver, context()); - translatedReceiver = getReceiver(); - translatedCallee = getCalleeExpression(); - } - - @NotNull - private ResolvedCall getResolvedCall() { - if (resolvedCall instanceof VariableAsFunctionResolvedCall) { - return ((VariableAsFunctionResolvedCall) resolvedCall).getFunctionCall(); - } - return resolvedCall; - } - - @Nullable - private JsExpression getReceiver() { - assert argumentsInfo != null : "the results of this function depends on the argumentsInfo"; - if (receiver == null) { - return null; - } - if (argumentsInfo.getCachedReceiver() != null) { - return argumentsInfo.getCachedReceiver().assignmentExpression(); - } - return receiver; - } - - @Nullable - private JsExpression getCalleeExpression() { - assert argumentsInfo != null : "the results of this function depends on the argumentsInfo"; - if (isNativeFunctionCall && argumentsInfo.isHasSpreadOperator()) { - JsName functionName = context().getNameForDescriptor(resolvedCall.getCandidateDescriptor()); - return new JsNameRef("apply", functionName.makeRef()); - } - CallableDescriptor candidateDescriptor = resolvedCall.getCandidateDescriptor(); - if (candidateDescriptor instanceof ExpressionAsFunctionDescriptor) { - return translateExpressionAsFunction(); - } - if (resolvedCall instanceof VariableAsFunctionResolvedCall) { - return translateVariableForVariableAsFunctionResolvedCall(); - } - return null; - } - - @NotNull - //TODO: looks hacky and should be modified soon - private JsExpression translateVariableForVariableAsFunctionResolvedCall() { - JetExpression callee = PsiUtils.getCallee(expression); - if (callee instanceof JetSimpleNameExpression) { - return ReferenceTranslator.getAccessTranslator((JetSimpleNameExpression) callee, receiver, context()).translateAsGet(); - } - assert receiver != null; - return Translation.translateAsExpression(callee, context()); - } - - @NotNull - private JsExpression translateExpressionAsFunction() { - return Translation.translateAsExpression(getCallee(expression), context()); - } - } diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/reference/FunctionCallCases.kt b/js/js.translator/src/org/jetbrains/k2js/translate/reference/FunctionCallCases.kt index 8d8db4159f7..207656963f8 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/reference/FunctionCallCases.kt +++ b/js/js.translator/src/org/jetbrains/k2js/translate/reference/FunctionCallCases.kt @@ -97,6 +97,28 @@ class DelegateFunctionIntrinsic(callInfo: FunctionCallInfo) : FunctionCallCase(c } } +class InvokeIntrinsic(callInfo: FunctionCallInfo) : FunctionCallCase(callInfo) { + class object { + fun canApply(callInfo: FunctionCallInfo): Boolean { + if (!callInfo.callableDescriptor.getName().asString().equals("invoke")) + return false + val parameterCount = callInfo.callableDescriptor.getValueParameters().size() + val funDeclaration = callInfo.callableDescriptor.getContainingDeclaration() + return funDeclaration == ((if (callInfo.callableDescriptor.getReceiverParameter() == null) + KotlinBuiltIns.getInstance().getFunction(parameterCount) + else + KotlinBuiltIns.getInstance().getExtensionFunction(parameterCount))) + } + } + + override fun FunctionCallInfo.thisObject(): JsExpression { + return JsInvocation(thisObject, argumentsInfo.getTranslateArguments()) + } + override fun FunctionCallInfo.bothReceivers(): JsExpression { + return JsInvocation(thisObject, addReceiverToArgs(receiverObject!!, argumentsInfo.getTranslateArguments())) + } +} + class ConstructorCallCase(callInfo: FunctionCallInfo) : FunctionCallCase(callInfo) { override fun FunctionCallInfo.noReceivers(): JsExpression { return JsNew(context.getQualifiedReference(callableDescriptor), argumentsInfo.getTranslateArguments()) @@ -138,6 +160,7 @@ fun createFunctionCases(): CallCaseDispatcher() caseDispatcher.addCase(::ExpressionAsFunctionDescriptorIntrinsic) {ExpressionAsFunctionDescriptorIntrinsic.canApply(it)} + caseDispatcher.addCase(::InvokeIntrinsic) {InvokeIntrinsic.canApply(it)} caseDispatcher.addCase { DelegateFunctionIntrinsic(it).intrinsic() } diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/utils/BindingUtils.java b/js/js.translator/src/org/jetbrains/k2js/translate/utils/BindingUtils.java index 5f7819fa696..edcb971dcca 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/utils/BindingUtils.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/utils/BindingUtils.java @@ -156,10 +156,13 @@ public final class BindingUtils { } @NotNull - public static ResolvedCall getResolvedCallForCallExpression(@NotNull BindingContext context, + public static ResolvedCall getResolvedCallForCallExpression(@NotNull BindingContext context, @NotNull JetCallExpression expression) { JetExpression calleeExpression = PsiUtils.getCallee(expression); - return getResolvedCall(context, calleeExpression); + ResolvedCall resolvedCall = getResolvedCall(context, calleeExpression); + assert resolvedCall.getResultingDescriptor() instanceof FunctionDescriptor + : message(expression, "ResolvedCall for this expression must be ResolvedCall"); + return (ResolvedCall) resolvedCall; } public static boolean isVariableReassignment(@NotNull BindingContext context, @NotNull JetExpression expression) {