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.navigation.ItemPresentation;
021 import com.intellij.navigation.ItemPresentationProviders;
022 import com.intellij.psi.PsiElement;
023 import com.intellij.psi.tree.IElementType;
024 import com.intellij.psi.tree.TokenSet;
025 import com.intellij.psi.util.PsiTreeUtil;
026 import org.jetbrains.annotations.NotNull;
027 import org.jetbrains.annotations.Nullable;
028 import org.jetbrains.jet.JetNodeTypes;
029 import org.jetbrains.jet.lang.psi.stubs.PsiJetPropertyStub;
030 import org.jetbrains.jet.lang.psi.stubs.elements.JetStubElementTypes;
031 import org.jetbrains.jet.lexer.JetTokens;
032
033 import java.util.List;
034
035 import static org.jetbrains.jet.JetNodeTypes.PROPERTY_ACCESSOR;
036 import static org.jetbrains.jet.JetNodeTypes.PROPERTY_DELEGATE;
037 import static org.jetbrains.jet.lexer.JetTokens.*;
038
039 public class JetProperty extends JetTypeParameterListOwnerStub<PsiJetPropertyStub> implements JetVariableDeclaration,
040 JetCallableDeclaration {
041 public JetProperty(@NotNull ASTNode node) {
042 super(node);
043 }
044
045 public JetProperty(@NotNull PsiJetPropertyStub stub) {
046 super(stub, JetStubElementTypes.PROPERTY);
047 }
048
049 @Override
050 public <R, D> R accept(@NotNull JetVisitor<R, D> visitor, D data) {
051 return visitor.visitProperty(this, data);
052 }
053
054 @Override
055 public boolean isVar() {
056 PsiJetPropertyStub stub = getStub();
057 if (stub != null) {
058 return stub.isVar();
059 }
060
061 return getNode().findChildByType(JetTokens.VAR_KEYWORD) != null;
062 }
063
064 public boolean isLocal() {
065 PsiElement parent = getParent();
066 return !(parent instanceof JetFile || parent instanceof JetClassBody);
067 }
068
069 public boolean isTopLevel() {
070 PsiJetPropertyStub stub = getStub();
071 if (stub != null) {
072 return stub.isTopLevel();
073 }
074
075 return getParent() instanceof JetFile;
076 }
077
078 @Nullable
079 @Override
080 public JetParameterList getValueParameterList() {
081 return null;
082 }
083
084 @Override
085 @Nullable
086 public JetTypeReference getReceiverTypeRef() {
087 ASTNode node = getNode().getFirstChildNode();
088 while (node != null) {
089 IElementType tt = node.getElementType();
090 if (tt == JetTokens.COLON) break;
091
092 if (tt == JetNodeTypes.TYPE_REFERENCE) {
093 return (JetTypeReference) node.getPsi();
094 }
095 node = node.getTreeNext();
096 }
097
098 return null;
099 }
100
101 @Nullable
102 @Override
103 public JetTypeReference getReturnTypeRef() {
104 return getTypeRef();
105 }
106
107 @Override
108 @Nullable
109 public JetTypeReference getTypeRef() {
110 ASTNode node = getNode().getFirstChildNode();
111 boolean passedColon = false;
112 while (node != null) {
113 IElementType tt = node.getElementType();
114 if (tt == JetTokens.COLON) {
115 passedColon = true;
116 }
117 else if (tt == JetNodeTypes.TYPE_REFERENCE && passedColon) {
118 return (JetTypeReference) node.getPsi();
119 }
120 node = node.getTreeNext();
121 }
122
123 return null;
124 }
125
126 @NotNull
127 public List<JetPropertyAccessor> getAccessors() {
128 return findChildrenByType(PROPERTY_ACCESSOR);
129 }
130
131 @Nullable
132 public JetPropertyAccessor getGetter() {
133 for (JetPropertyAccessor accessor : getAccessors()) {
134 if (accessor.isGetter()) return accessor;
135 }
136
137 return null;
138 }
139
140 @Nullable
141 public JetPropertyAccessor getSetter() {
142 for (JetPropertyAccessor accessor : getAccessors()) {
143 if (accessor.isSetter()) return accessor;
144 }
145
146 return null;
147 }
148
149 @Nullable
150 public JetPropertyDelegate getDelegate() {
151 return (JetPropertyDelegate) findChildByType(PROPERTY_DELEGATE);
152 }
153
154 @Nullable
155 public JetExpression getDelegateExpression() {
156 JetPropertyDelegate delegate = getDelegate();
157 if (delegate != null) {
158 return delegate.getExpression();
159 }
160 return null;
161 }
162
163 @Override
164 @Nullable
165 public JetExpression getInitializer() {
166 return PsiTreeUtil.getNextSiblingOfType(findChildByType(EQ), JetExpression.class);
167 }
168
169 @Nullable
170 public JetExpression getDelegateExpressionOrInitializer() {
171 JetExpression expression = getDelegateExpression();
172 if (expression == null) {
173 return getInitializer();
174 }
175 return expression;
176 }
177
178 @Override
179 @NotNull
180 public ASTNode getValOrVarNode() {
181 ASTNode node = getNode().findChildByType(TokenSet.create(VAL_KEYWORD, VAR_KEYWORD));
182 assert node != null : "Val or var should always exist for property";
183 return node;
184 }
185
186 @Override
187 public ItemPresentation getPresentation() {
188 return ItemPresentationProviders.getItemPresentation(this);
189 }
190 }