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