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 }