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    
017    package org.jetbrains.k2js.translate.reference;
018    
019    import com.google.common.collect.Lists;
020    import com.google.dart.compiler.backend.js.ast.JsArrayLiteral;
021    import com.google.dart.compiler.backend.js.ast.JsExpression;
022    import org.jetbrains.annotations.NotNull;
023    import org.jetbrains.annotations.Nullable;
024    import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor;
025    import org.jetbrains.jet.lang.psi.JetCallExpression;
026    import org.jetbrains.jet.lang.psi.JetExpression;
027    import org.jetbrains.jet.lang.psi.ValueArgument;
028    import org.jetbrains.jet.lang.resolve.calls.model.*;
029    import org.jetbrains.k2js.translate.context.TranslationContext;
030    import org.jetbrains.k2js.translate.general.AbstractTranslator;
031    import org.jetbrains.k2js.translate.general.Translation;
032    
033    import java.util.Collections;
034    import java.util.List;
035    
036    import static org.jetbrains.k2js.translate.utils.BindingUtils.getDefaultArgument;
037    import static org.jetbrains.k2js.translate.utils.BindingUtils.getResolvedCallForCallExpression;
038    
039    public 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    }