EA-20339
[idea/community.git] / java / java-impl / src / com / intellij / psi / impl / source / PsiParameterImpl.java
1 /*
2  * Copyright 2000-2009 JetBrains s.r.o.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package com.intellij.psi.impl.source;
17
18 import com.intellij.lang.ASTNode;
19 import com.intellij.navigation.ItemPresentation;
20 import com.intellij.openapi.diagnostic.Logger;
21 import com.intellij.psi.*;
22 import com.intellij.psi.impl.CheckUtil;
23 import com.intellij.psi.impl.ElementPresentationUtil;
24 import com.intellij.psi.impl.PsiImplUtil;
25 import com.intellij.psi.impl.cache.TypeInfo;
26 import com.intellij.psi.impl.java.stubs.JavaStubElementTypes;
27 import com.intellij.psi.impl.java.stubs.PsiParameterStub;
28 import com.intellij.psi.impl.source.tree.ChildRole;
29 import com.intellij.psi.impl.source.tree.CompositeElement;
30 import com.intellij.psi.impl.source.tree.JavaSharedImplUtil;
31 import com.intellij.psi.presentation.java.JavaPresentationUtil;
32 import com.intellij.psi.search.LocalSearchScope;
33 import com.intellij.psi.search.SearchScope;
34 import com.intellij.ui.RowIcon;
35 import com.intellij.util.Icons;
36 import com.intellij.util.IncorrectOperationException;
37 import com.intellij.util.PatchedSoftReference;
38 import org.jetbrains.annotations.NotNull;
39
40 import javax.swing.*;
41 import java.util.Arrays;
42
43 public class PsiParameterImpl extends JavaStubPsiElement<PsiParameterStub> implements PsiParameter {
44   private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.source.PsiParameterImpl");
45   private volatile PatchedSoftReference<PsiType> myCachedType = null;
46
47   public PsiParameterImpl(final PsiParameterStub stub) {
48     super(stub, JavaStubElementTypes.PARAMETER);
49   }
50
51   public PsiParameterImpl(final ASTNode node) {
52     super(node);
53   }
54
55   public void subtreeChanged() {
56     super.subtreeChanged();
57     myCachedType = null;
58   }
59
60   protected Object clone() {
61     PsiParameterImpl clone = (PsiParameterImpl)super.clone();
62     clone.myCachedType = null;
63
64     return clone;
65   }
66
67   @NotNull
68   public final String getName() {
69     final PsiParameterStub stub = getStub();
70     if (stub != null) {
71       return stub.getName();
72     }
73     return getNameIdentifier().getText();
74   }
75
76   public PsiElement setName(@NotNull String name) throws IncorrectOperationException {
77     PsiImplUtil.setName(getNameIdentifier(), name);
78     return this;
79   }
80
81   @NotNull
82   public final PsiIdentifier getNameIdentifier() {
83     return (PsiIdentifier)getNode().findChildByRoleAsPsiElement(ChildRole.NAME);
84   }
85
86   @NotNull
87   public CompositeElement getNode() {
88     return (CompositeElement)super.getNode();
89   }
90
91   @NotNull
92   public PsiType getType() {
93     final PsiParameterStub stub = getStub();
94     if (stub != null) {
95       PatchedSoftReference<PsiType> cachedType = myCachedType;
96       if (cachedType != null) {
97         PsiType type = cachedType.get();
98         if (type != null) return type;
99       }
100
101       String typeText = TypeInfo.createTypeText(stub.getType(true));
102       try {
103         final PsiType type = JavaPsiFacade.getInstance(getProject()).getParserFacade().createTypeFromText(typeText, this);
104         myCachedType = new PatchedSoftReference<PsiType>(type);
105         return type;
106       }
107       catch (IncorrectOperationException e) {
108         LOG.error(e);
109         return null;
110       }
111     }
112
113     myCachedType = null;
114     return JavaSharedImplUtil.getType(this);
115   }
116
117   public PsiType getTypeNoResolve() {
118     final PsiParameterStub stub = getStub();
119     if (stub != null) {
120       String typeText = TypeInfo.createTypeText(stub.getType(false));
121       try {
122         return JavaPsiFacade.getInstance(getProject()).getParserFacade().createTypeFromText(typeText, this);
123       }
124       catch (IncorrectOperationException e) {
125         LOG.error(e);
126         return null;
127       }
128     }
129     PsiTypeElement typeElement = getTypeElement();
130     PsiIdentifier nameIdentifier = getNameIdentifier();
131     return JavaSharedImplUtil.getTypeNoResolve(typeElement, nameIdentifier, this);
132   }
133
134   @NotNull
135   public PsiTypeElement getTypeElement() {
136     return (PsiTypeElement)getNode().findChildByRoleAsPsiElement(ChildRole.TYPE);
137   }
138
139   @NotNull
140   public PsiModifierList getModifierList() {
141     return getStubOrPsiChild(JavaStubElementTypes.MODIFIER_LIST);
142   }
143
144   public boolean hasModifierProperty(@NotNull String name) {
145     return getModifierList().hasModifierProperty(name);
146   }
147
148   public PsiExpression getInitializer() {
149     return null;
150   }
151
152   public boolean hasInitializer() {
153     return false;
154   }
155
156   public Object computeConstantValue() {
157     return null;
158   }
159
160   public void normalizeDeclaration() throws IncorrectOperationException {
161     CheckUtil.checkWritable(this);
162     JavaSharedImplUtil.normalizeBrackets(this);
163   }
164
165   public void accept(@NotNull PsiElementVisitor visitor) {
166     if (visitor instanceof JavaElementVisitor) {
167       ((JavaElementVisitor)visitor).visitParameter(this);
168     }
169     else {
170       visitor.visitElement(this);
171     }
172   }
173
174   public String toString() {
175     return "PsiParameter:" + getName();
176   }
177
178   @NotNull
179   public PsiElement getDeclarationScope() {
180     final PsiElement parent = getParent();
181     if (parent == null) return this;
182     if (parent instanceof PsiParameterList){
183       return parent.getParent();
184     }
185     if (parent instanceof PsiForeachStatement) {
186       return parent;
187     }
188     if (parent instanceof PsiCatchSection) {
189       return parent;
190     }
191     PsiElement[] children = parent.getChildren();
192     //noinspection ConstantConditions
193     if (children != null) {
194       for(int i = 0; i < children.length; i++){
195         if (children[i].equals(this)){
196           while(!(children[i] instanceof PsiCodeBlock)){
197             i++;
198           }
199           return children[i];
200         }
201       }
202     }
203     LOG.error("codeblock not found among parameter' "+this+" parents children: "+ Arrays.asList(children));
204     return null;
205   }
206
207   public boolean isVarArgs() {
208     final PsiParameterStub stub = getStub();
209     if (stub != null) {
210       return stub.isParameterTypeEllipsis();
211     }
212
213     myCachedType = null;
214     return SourceTreeToPsiMap.psiElementToTree(getTypeElement()).findChildByType(JavaTokenType.ELLIPSIS) != null;
215   }
216
217   @NotNull
218   public PsiAnnotation[] getAnnotations() {
219     return getModifierList().getAnnotations();
220   }
221
222   public ItemPresentation getPresentation() {
223     return JavaPresentationUtil.getVariablePresentation(this);
224   }
225
226   public Icon getElementIcon(final int flags) {
227     final RowIcon baseIcon = createLayeredIcon(Icons.PARAMETER_ICON, 0);
228     return ElementPresentationUtil.addVisibilityIcon(this, flags, baseIcon);
229   }
230
231   @NotNull
232   public SearchScope getUseScope() {
233     final PsiElement declarationScope = getDeclarationScope();
234     return new LocalSearchScope(declarationScope);
235   }
236 }