e7dd313c5fc46348e3b7be70f56f617145c55cf7
[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 instanceof PsiParameterList){
182       return parent.getParent();
183     }
184     if (parent instanceof PsiForeachStatement) {
185       return parent;
186     }
187     if (parent instanceof PsiCatchSection) {
188       return parent;
189     }
190     PsiElement[] children = parent.getChildren();
191     for(int i = 0; i < children.length; i++){
192       if (children[i].equals(this)){
193         while(!(children[i] instanceof PsiCodeBlock)){
194           i++;
195         }
196         return children[i];
197       }
198     }
199     LOG.error("codeblock not found among parameter' "+this+" parents children: "+ Arrays.asList(children));
200     return null;
201   }
202
203   public boolean isVarArgs() {
204     final PsiParameterStub stub = getStub();
205     if (stub != null) {
206       return stub.isParameterTypeEllipsis();
207     }
208
209     myCachedType = null;
210     return SourceTreeToPsiMap.psiElementToTree(getTypeElement()).findChildByType(JavaTokenType.ELLIPSIS) != null;
211   }
212
213   @NotNull
214   public PsiAnnotation[] getAnnotations() {
215     return getModifierList().getAnnotations();
216   }
217
218   public ItemPresentation getPresentation() {
219     return JavaPresentationUtil.getVariablePresentation(this);
220   }
221
222   public Icon getElementIcon(final int flags) {
223     final RowIcon baseIcon = createLayeredIcon(Icons.PARAMETER_ICON, 0);
224     return ElementPresentationUtil.addVisibilityIcon(this, flags, baseIcon);
225   }
226
227   @NotNull
228   public SearchScope getUseScope() {
229     final PsiElement declarationScope = getDeclarationScope();
230     return new LocalSearchScope(declarationScope);
231   }
232 }