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.dart.compiler.backend.js.ast.JsArrayLiteral;
020    import com.google.dart.compiler.backend.js.ast.JsExpression;
021    import com.intellij.util.SmartList;
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.ArrayList;
034    import java.util.Collections;
035    import java.util.List;
036    
037    import static org.jetbrains.k2js.translate.utils.BindingUtils.getDefaultArgument;
038    import static org.jetbrains.k2js.translate.utils.BindingUtils.getResolvedCallForCallExpression;
039    
040    public abstract class AbstractCallExpressionTranslator extends AbstractTranslator {
041    
042        @NotNull
043        protected final JetCallExpression expression;
044        @NotNull
045        protected final ResolvedCall<?> resolvedCall;
046        @Nullable
047        protected final JsExpression receiver;
048        @NotNull
049        protected final CallType callType;
050    
051        protected AbstractCallExpressionTranslator(@NotNull JetCallExpression expression,
052                @Nullable JsExpression receiver,
053                @NotNull CallType type, @NotNull TranslationContext context) {
054            super(context);
055            this.expression = expression;
056            this.resolvedCall = getResolvedCallForCallExpression(bindingContext(), expression);
057            this.receiver = receiver;
058            this.callType = type;
059        }
060    
061        protected abstract boolean shouldWrapVarargInArray();
062    
063        protected void translateSingleArgument(
064                @NotNull ResolvedValueArgument actualArgument,
065                @NotNull ValueParameterDescriptor parameterDescriptor,
066                @NotNull List<JsExpression> result
067        ) {
068            List<ValueArgument> valueArguments = actualArgument.getArguments();
069            if (actualArgument instanceof VarargValueArgument) {
070                translateVarargArgument(valueArguments, result);
071            }
072            else if (actualArgument instanceof DefaultValueArgument) {
073                JetExpression defaultArgument = getDefaultArgument(bindingContext(), parameterDescriptor);
074                result.add(Translation.translateAsExpression(defaultArgument, context()));
075            }
076            else {
077                assert actualArgument instanceof ExpressionValueArgument;
078                assert valueArguments.size() == 1;
079                JetExpression argumentExpression = valueArguments.get(0).getArgumentExpression();
080                assert argumentExpression != null;
081                result.add(Translation.translateAsExpression(argumentExpression, context()));
082            }
083        }
084    
085        private void translateVarargArgument(@NotNull List<ValueArgument> arguments, @NotNull List<JsExpression> result) {
086            if (arguments.isEmpty()) {
087                if (shouldWrapVarargInArray()) {
088                    result.add(new JsArrayLiteral(Collections.<JsExpression>emptyList()));
089                }
090                return;
091            }
092    
093            List<JsExpression> list;
094            if (shouldWrapVarargInArray()) {
095                list = arguments.size() == 1 ? new SmartList<JsExpression>() : new ArrayList<JsExpression>(arguments.size());
096                result.add(new JsArrayLiteral(list));
097            }
098            else {
099                list = result;
100            }
101            for (ValueArgument argument : arguments) {
102                JetExpression argumentExpression = argument.getArgumentExpression();
103                assert argumentExpression != null;
104                list.add(Translation.translateAsExpression(argumentExpression, context()));
105            }
106        }
107    }