001/*
002 * Copyright 2010-2013 JetBrains s.r.o.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017package org.jetbrains.k2js.translate.reference;
018
019import com.google.common.collect.Lists;
020import com.google.dart.compiler.backend.js.ast.JsArrayLiteral;
021import com.google.dart.compiler.backend.js.ast.JsExpression;
022import org.jetbrains.annotations.NotNull;
023import org.jetbrains.annotations.Nullable;
024import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor;
025import org.jetbrains.jet.lang.psi.JetCallExpression;
026import org.jetbrains.jet.lang.psi.JetExpression;
027import org.jetbrains.jet.lang.psi.ValueArgument;
028import org.jetbrains.jet.lang.resolve.calls.model.*;
029import org.jetbrains.k2js.translate.context.TranslationContext;
030import org.jetbrains.k2js.translate.general.AbstractTranslator;
031import org.jetbrains.k2js.translate.general.Translation;
032
033import java.util.Collections;
034import java.util.List;
035
036import static org.jetbrains.k2js.translate.utils.BindingUtils.getDefaultArgument;
037import static org.jetbrains.k2js.translate.utils.BindingUtils.getResolvedCallForCallExpression;
038
039public abstract class AbstractCallExpressionTranslator extends AbstractTranslator {
040
041    @NotNull
042    protected final JetCallExpression expression;
043    @NotNull
044    protected final ResolvedCall<?> resolvedCall;
045    @Nullable
046    protected final JsExpression receiver;
047    @NotNull
048    protected final CallType callType;
049
050    protected AbstractCallExpressionTranslator(@NotNull JetCallExpression expression,
051            @Nullable JsExpression receiver,
052            @NotNull CallType type, @NotNull TranslationContext context) {
053        super(context);
054        this.expression = expression;
055        this.resolvedCall = getResolvedCallForCallExpression(bindingContext(), expression);
056        this.receiver = receiver;
057        this.callType = type;
058    }
059
060    protected abstract boolean shouldWrapVarargInArray();
061
062    @NotNull
063    protected List<JsExpression> translateSingleArgument(@NotNull ResolvedValueArgument actualArgument,
064            @NotNull ValueParameterDescriptor parameterDescriptor) {
065        List<ValueArgument> valueArguments = actualArgument.getArguments();
066        if (actualArgument instanceof VarargValueArgument) {
067            return translateVarargArgument(valueArguments);
068        }
069        if (actualArgument instanceof DefaultValueArgument) {
070            JetExpression defaultArgument = getDefaultArgument(bindingContext(), parameterDescriptor);
071            return Collections.singletonList(Translation.translateAsExpression(defaultArgument, context()));
072        }
073        assert actualArgument instanceof ExpressionValueArgument;
074        assert valueArguments.size() == 1;
075        JetExpression argumentExpression = valueArguments.get(0).getArgumentExpression();
076        assert argumentExpression != null;
077        return Collections.singletonList(Translation.translateAsExpression(argumentExpression, context()));
078    }
079
080    @NotNull
081    private List<JsExpression> translateVarargArgument(@NotNull List<ValueArgument> arguments) {
082        List<JsExpression> translatedArgs = Lists.newArrayList();
083        for (ValueArgument argument : arguments) {
084            JetExpression argumentExpression = argument.getArgumentExpression();
085            assert argumentExpression != null;
086            translatedArgs.add(Translation.translateAsExpression(argumentExpression, context()));
087        }
088        if (shouldWrapVarargInArray()) {
089            return wrapInArrayLiteral(translatedArgs);
090        }
091        return translatedArgs;
092    }
093
094    @NotNull
095    private static List<JsExpression> wrapInArrayLiteral(@NotNull List<JsExpression> translatedArgs) {
096        return Collections.<JsExpression>singletonList(new JsArrayLiteral(translatedArgs));
097    }
098}