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.psi.tree.IElementType;
025import com.intellij.psi.tree.TokenSet;
026import org.jetbrains.annotations.NotNull;
027import org.jetbrains.annotations.Nullable;
028import org.jetbrains.jet.lang.parsing.JetExpressionParsing;
029import org.jetbrains.jet.lang.resolve.name.Name;
030import org.jetbrains.jet.lexer.JetTokens;
031
032import static org.jetbrains.jet.lexer.JetTokens.*;
033
034public class JetSimpleNameExpression extends JetReferenceExpression {
035    public static final TokenSet REFERENCE_TOKENS = TokenSet.orSet(LABELS, TokenSet.create(IDENTIFIER, FIELD_IDENTIFIER, THIS_KEYWORD, SUPER_KEYWORD));
036
037    public JetSimpleNameExpression(@NotNull ASTNode node) {
038        super(node);
039    }
040
041    /**
042     * null if it's not a code expression
043     * @return receiver expression
044     */
045    @Nullable
046    public JetExpression getReceiverExpression() {
047        PsiElement parent = getParent();
048        if (parent instanceof JetQualifiedExpression && !isImportDirectiveExpression()) {
049            JetExpression receiverExpression = ((JetQualifiedExpression) parent).getReceiverExpression();
050            // Name expression can't be receiver for itself
051            if (receiverExpression != this) {
052                return receiverExpression;
053            }
054        }
055        else if (parent instanceof JetCallExpression) {
056            //This is in case `a().b()`
057            JetCallExpression callExpression = (JetCallExpression) parent;
058            parent = callExpression.getParent();
059            if (parent instanceof JetQualifiedExpression) {
060                JetQualifiedExpression qualifiedExpression = (JetQualifiedExpression) parent;
061                return qualifiedExpression.getReceiverExpression();
062            }
063        }
064
065        return null;
066    }
067
068    public boolean isImportDirectiveExpression() {
069        PsiElement parent = getParent();
070        if (parent == null) return false;
071        else return parent instanceof JetImportDirective ||
072                    parent.getParent() instanceof JetImportDirective;
073    }
074
075    @NotNull
076    public String getReferencedName() {
077        String text = getReferencedNameElement().getNode().getText();
078        return JetPsiUtil.unquoteIdentifierOrFieldReference(text);
079    }
080
081    @NotNull
082    public Name getReferencedNameAsName() {
083        String name = getReferencedName();
084        return Name.identifierNoValidate(name);
085    }
086
087    @NotNull
088    public PsiElement getReferencedNameElement() {
089        PsiElement element = findChildByType(REFERENCE_TOKENS);
090        if (element == null) {
091            element = findChildByType(JetExpressionParsing.ALL_OPERATIONS);
092        }
093
094        if (element != null) {
095            return element;
096        }
097
098        return this;
099    }
100
101    @Nullable
102    public PsiElement getIdentifier() {
103        return findChildByType(JetTokens.IDENTIFIER);
104    }
105
106    @Nullable @IfNotParsed
107    public IElementType getReferencedNameElementType() {
108        return getReferencedNameElement().getNode().getElementType();
109    }
110
111    @NotNull
112    @Override
113    public PsiReference[] getReferences() {
114        return ReferenceProvidersRegistry.getReferencesFromProviders(this, PsiReferenceService.Hints.NO_HINTS);
115    }
116
117    @Nullable
118    @Override
119    public PsiReference getReference() {
120        PsiReference[] references = getReferences();
121        if (references.length == 1) return references[0];
122        else return null;
123    }
124
125    @Override
126    public void accept(@NotNull JetVisitorVoid visitor) {
127        visitor.visitSimpleNameExpression(this);
128    }
129
130    @Override
131    public <R, D> R accept(@NotNull JetVisitor<R, D> visitor, D data) {
132        return visitor.visitSimpleNameExpression(this, data);
133    }
134}