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.psi.PsiReference;
022    import com.intellij.psi.PsiReferenceService;
023    import com.intellij.psi.impl.source.resolve.reference.ReferenceProvidersRegistry;
024    import com.intellij.psi.tree.IElementType;
025    import com.intellij.psi.tree.TokenSet;
026    import org.jetbrains.annotations.NotNull;
027    import org.jetbrains.annotations.Nullable;
028    import org.jetbrains.jet.lang.parsing.JetExpressionParsing;
029    import org.jetbrains.jet.lang.resolve.name.Name;
030    import org.jetbrains.jet.lexer.JetTokens;
031    
032    import static org.jetbrains.jet.lexer.JetTokens.*;
033    
034    public 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    }