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