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.jet.lang.psi;
018
019import com.intellij.lang.ASTNode;
020import com.intellij.psi.PsiElement;
021import com.intellij.psi.PsiReference;
022import com.intellij.psi.PsiReferenceService;
023import com.intellij.psi.impl.source.resolve.reference.ReferenceProvidersRegistry;
024import com.intellij.util.SmartList;
025import org.jetbrains.annotations.NotNull;
026import org.jetbrains.annotations.Nullable;
027import org.jetbrains.jet.JetNodeTypes;
028import org.jetbrains.jet.lexer.JetTokens;
029
030import java.util.Collections;
031import java.util.List;
032
033public class JetCallExpression extends JetReferenceExpression implements JetCallElement {
034    public JetCallExpression(@NotNull ASTNode node) {
035        super(node);
036    }
037
038    @Nullable
039    @Override
040    public PsiReference getReference() {
041        PsiReference[] references = getReferences();
042        if (references.length == 1) return references[0];
043        else return null;
044    }
045
046    @NotNull
047    @Override
048    public PsiReference[] getReferences() {
049        return ReferenceProvidersRegistry.getReferencesFromProviders(this);
050    }
051
052    @Override
053    public void accept(@NotNull JetVisitorVoid visitor) {
054        visitor.visitCallExpression(this);
055    }
056
057    @Override
058    public <R, D> R accept(@NotNull JetVisitor<R, D> visitor, D data) {
059        return visitor.visitCallExpression(this, data);
060    }
061
062    @Override
063    @Nullable
064    public JetExpression getCalleeExpression() {
065        return findChildByClass(JetExpression.class);
066    }
067
068    @Override
069    @Nullable
070    public JetValueArgumentList getValueArgumentList() {
071        return (JetValueArgumentList) findChildByType(JetNodeTypes.VALUE_ARGUMENT_LIST);
072    }
073
074    @Nullable
075    public JetTypeArgumentList getTypeArgumentList() {
076        return (JetTypeArgumentList) findChildByType(JetNodeTypes.TYPE_ARGUMENT_LIST);
077    }
078
079    @Override
080    @NotNull
081    public List<JetExpression> getFunctionLiteralArguments() {
082        JetExpression calleeExpression = getCalleeExpression();
083        ASTNode node;
084        if (calleeExpression instanceof JetFunctionLiteralExpression) {
085            node = calleeExpression.getNode().getTreeNext();
086        }
087        else {
088            node = getNode().getFirstChildNode();
089        }
090        List<JetExpression> result = new SmartList<JetExpression>();
091        while (node != null) {
092            PsiElement psi = node.getPsi();
093            if (psi instanceof JetFunctionLiteralExpression) {
094                result.add((JetFunctionLiteralExpression) psi);
095            }
096            else if (psi instanceof JetPrefixExpression) {
097                JetPrefixExpression prefixExpression = (JetPrefixExpression) psi;
098                if (JetTokens.LABELS.contains(prefixExpression.getOperationReference().getReferencedNameElementType())) {
099                    JetExpression labeledExpression = prefixExpression.getBaseExpression();
100                    if (labeledExpression instanceof JetFunctionLiteralExpression) {
101                        result.add(labeledExpression);
102                    }
103                }
104            }
105            node = node.getTreeNext();
106        }
107        return result;
108    }
109
110    @Override
111    @NotNull
112    public List<? extends ValueArgument> getValueArguments() {
113        JetValueArgumentList list = getValueArgumentList();
114        return list != null ? list.getArguments() : Collections.<JetValueArgument>emptyList();
115    }
116
117    @NotNull
118    public List<JetTypeProjection> getTypeArguments() {
119        JetTypeArgumentList list = getTypeArgumentList();
120        return list != null ? list.getArguments() : Collections.<JetTypeProjection>emptyList();
121    }
122}