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.JsExpression;
020    import com.google.dart.compiler.backend.js.ast.JsInvocation;
021    import com.google.dart.compiler.backend.js.ast.metadata.MetadataPackage;
022    import org.jetbrains.annotations.NotNull;
023    import org.jetbrains.annotations.Nullable;
024    import org.jetbrains.jet.lang.descriptors.CallableDescriptor;
025    import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
026    import org.jetbrains.jet.lang.descriptors.SimpleFunctionDescriptor;
027    import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor;
028    import org.jetbrains.jet.lang.psi.JetCallExpression;
029    import org.jetbrains.jet.lang.resolve.calls.callUtil.CallUtilPackage;
030    import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall;
031    import org.jetbrains.jet.lang.resolve.calls.model.VariableAsFunctionResolvedCall;
032    import org.jetbrains.jet.lang.types.lang.InlineStrategy;
033    import org.jetbrains.jet.lang.types.lang.InlineUtil;
034    import org.jetbrains.k2js.translate.callTranslator.CallTranslator;
035    import org.jetbrains.k2js.translate.context.TranslationContext;
036    
037    public final class CallExpressionTranslator extends AbstractCallExpressionTranslator {
038    
039        @NotNull
040        public static JsExpression translate(
041                @NotNull JetCallExpression expression,
042                @Nullable JsExpression receiver,
043                @NotNull TranslationContext context
044        ) {
045            JsExpression callExpression = (new CallExpressionTranslator(expression, receiver, context)).translate();
046    
047            if (shouldBeInlined(expression, context)
048                && callExpression instanceof JsInvocation) {
049    
050                MetadataPackage.setInlineStrategy((JsInvocation) callExpression, InlineStrategy.IN_PLACE);
051            }
052    
053            return callExpression;
054        }
055    
056        public static boolean shouldBeInlined(@NotNull JetCallExpression expression, @NotNull TranslationContext context) {
057            if (!context.getConfig().isInlineEnabled()) return false;
058    
059            ResolvedCall<?> resolvedCall = CallUtilPackage.getResolvedCall(expression, context.bindingContext());
060            assert resolvedCall != null;
061    
062            CallableDescriptor descriptor;
063    
064            if (resolvedCall instanceof VariableAsFunctionResolvedCall) {
065                descriptor = ((VariableAsFunctionResolvedCall) resolvedCall).getVariableCall().getCandidateDescriptor();
066            } else {
067                descriptor = resolvedCall.getCandidateDescriptor();
068            }
069    
070            if (descriptor instanceof SimpleFunctionDescriptor) {
071                return ((SimpleFunctionDescriptor) descriptor).getInlineStrategy().isInline();
072            }
073    
074            if (descriptor instanceof ValueParameterDescriptor) {
075                DeclarationDescriptor containingDescriptor = descriptor.getContainingDeclaration();
076                return InlineUtil.getInlineType(containingDescriptor).isInline()
077                       && !InlineUtil.hasNoinlineAnnotation(descriptor);
078            }
079    
080            return false;
081        }
082    
083        private CallExpressionTranslator(
084                @NotNull JetCallExpression expression,
085                @Nullable JsExpression receiver,
086                @NotNull TranslationContext context
087        ) {
088            super(expression, receiver, context);
089        }
090    
091        @NotNull
092        private JsExpression translate() {
093            return CallTranslator.INSTANCE$.translate(context(), resolvedCall, receiver);
094        }
095    }