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