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.jet.lang.psi;
018    
019    import com.intellij.lang.ASTNode;
020    import com.intellij.psi.PsiElement;
021    import com.intellij.util.SmartList;
022    import org.jetbrains.annotations.NotNull;
023    import org.jetbrains.annotations.Nullable;
024    import org.jetbrains.jet.JetNodeTypes;
025    import org.jetbrains.jet.lexer.JetTokens;
026    
027    import java.util.Collections;
028    import java.util.List;
029    
030    public class JetCallExpression extends JetExpressionImpl implements JetCallElement, JetReferenceExpression {
031        public JetCallExpression(@NotNull ASTNode node) {
032            super(node);
033        }
034    
035        @Override
036        public <R, D> R accept(@NotNull JetVisitor<R, D> visitor, D data) {
037            return visitor.visitCallExpression(this, data);
038        }
039    
040        @Override
041        @Nullable
042        public JetExpression getCalleeExpression() {
043            return findChildByClass(JetExpression.class);
044        }
045    
046        @Override
047        @Nullable
048        public JetValueArgumentList getValueArgumentList() {
049            return (JetValueArgumentList) findChildByType(JetNodeTypes.VALUE_ARGUMENT_LIST);
050        }
051    
052        @Nullable
053        public JetTypeArgumentList getTypeArgumentList() {
054            return (JetTypeArgumentList) findChildByType(JetNodeTypes.TYPE_ARGUMENT_LIST);
055        }
056    
057        /**
058         * Normally there should be only one (or zero) function literal arguments.
059         * The returned value is a list for better handling of commonly made mistake of a function taking a lambda and returning another function.
060         * Most of users can simply ignore lists of more than one element.
061         */
062        @Override
063        @NotNull
064        public List<JetExpression> getFunctionLiteralArguments() {
065            JetExpression calleeExpression = getCalleeExpression();
066            ASTNode node;
067            if (calleeExpression instanceof JetFunctionLiteralExpression) {
068                node = calleeExpression.getNode().getTreeNext();
069            }
070            else {
071                node = getNode().getFirstChildNode();
072            }
073            List<JetExpression> result = new SmartList<JetExpression>();
074            while (node != null) {
075                PsiElement psi = node.getPsi();
076                if (psi instanceof JetFunctionLiteralExpression) {
077                    result.add((JetFunctionLiteralExpression) psi);
078                }
079                else if (psi instanceof JetLabeledExpression) {
080                    JetLabeledExpression labeledExpression = (JetLabeledExpression) psi;
081                    JetExpression baseExpression = labeledExpression.getBaseExpression();
082                    if (baseExpression instanceof JetFunctionLiteralExpression) {
083                        result.add(labeledExpression);
084                    }
085                }
086                node = node.getTreeNext();
087            }
088            return result;
089        }
090    
091        @Override
092        @NotNull
093        public List<? extends ValueArgument> getValueArguments() {
094            JetValueArgumentList list = getValueArgumentList();
095            return list != null ? list.getArguments() : Collections.<JetValueArgument>emptyList();
096        }
097    
098        @NotNull
099        public List<JetTypeProjection> getTypeArguments() {
100            JetTypeArgumentList list = getTypeArgumentList();
101            return list != null ? list.getArguments() : Collections.<JetTypeProjection>emptyList();
102        }
103    }