2 * Copyright 2000-2009 JetBrains s.r.o.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
16 package com
.intellij
.psi
.impl
.source
.tree
.java
;
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
.*;
23 import com
.intellij
.psi
.impl
.source
.Constants
;
24 import com
.intellij
.psi
.impl
.source
.JavaDummyHolder
;
25 import com
.intellij
.psi
.impl
.source
.SourceTreeToPsiMap
;
26 import com
.intellij
.psi
.impl
.source
.codeStyle
.CodeEditUtil
;
27 import com
.intellij
.psi
.impl
.source
.jsp
.JspContextManager
;
28 import com
.intellij
.psi
.impl
.source
.jsp
.jspJava
.JspCodeBlock
;
29 import com
.intellij
.psi
.impl
.source
.tree
.*;
30 import com
.intellij
.psi
.jsp
.JspElementType
;
31 import com
.intellij
.psi
.jsp
.JspFile
;
32 import com
.intellij
.psi
.jsp
.JspSpiUtil
;
33 import com
.intellij
.psi
.presentation
.java
.JavaPresentationUtil
;
34 import com
.intellij
.psi
.scope
.PsiScopeProcessor
;
35 import com
.intellij
.psi
.search
.LocalSearchScope
;
36 import com
.intellij
.psi
.search
.SearchScope
;
37 import com
.intellij
.psi
.tree
.ChildRoleBase
;
38 import com
.intellij
.psi
.tree
.IElementType
;
39 import com
.intellij
.ui
.RowIcon
;
40 import com
.intellij
.util
.CharTable
;
41 import com
.intellij
.util
.Icons
;
42 import com
.intellij
.util
.IncorrectOperationException
;
43 import com
.intellij
.util
.Processor
;
44 import gnu
.trove
.THashSet
;
45 import org
.jetbrains
.annotations
.NotNull
;
50 public class PsiLocalVariableImpl
extends CompositePsiElement
implements PsiLocalVariable
, PsiVariableEx
, Constants
{
51 private static final Logger LOG
= Logger
.getInstance("#com.intellij.psi.impl.source.tree.java.PsiLocalVariableImpl");
53 private volatile String myCachedName
= null;
55 public PsiLocalVariableImpl() {
56 super(LOCAL_VARIABLE
);
59 public void clearCaches() {
65 public final PsiIdentifier
getNameIdentifier() {
66 return (PsiIdentifier
)findChildByRoleAsPsiElement(ChildRole
.NAME
);
70 public final String
getName() {
71 String cachedName
= myCachedName
;
72 if (cachedName
== null){
73 myCachedName
= cachedName
= getNameIdentifier().getText();
78 public void setInitializer(PsiExpression initializer
) throws IncorrectOperationException
{
79 JavaSharedImplUtil
.setInitializer(this, initializer
);
82 public PsiElement
setName(@NotNull String name
) throws IncorrectOperationException
{
83 PsiImplUtil
.setName(getNameIdentifier(), name
);
88 public final PsiType
getType() {
89 return JavaSharedImplUtil
.getType(this);
93 public PsiTypeElement
getTypeElement() {
94 ASTNode first
= getTreeParent().findChildByType(LOCAL_VARIABLE
);
95 return (PsiTypeElement
)SourceTreeToPsiMap
.treeElementToPsi(first
.findChildByType(TYPE
));
98 public PsiModifierList
getModifierList() {
99 CompositeElement parent
= getTreeParent();
100 if (parent
== null) return null;
101 CompositeElement first
= (CompositeElement
)parent
.findChildByType(LOCAL_VARIABLE
);
102 return (PsiModifierList
)first
.findChildByRoleAsPsiElement(ChildRole
.MODIFIER_LIST
);
105 public boolean hasModifierProperty(@NotNull String name
) {
106 return getModifierList().hasModifierProperty(name
);
109 public PsiExpression
getInitializer() {
110 return (PsiExpression
)findChildByRoleAsPsiElement(ChildRole
.INITIALIZER
);
113 public boolean hasInitializer() {
114 return getInitializer() != null;
117 public Object
computeConstantValue() {
118 return computeConstantValue(new THashSet
<PsiVariable
>());
121 public Object
computeConstantValue(Set
<PsiVariable
> visitedVars
) {
122 if (!hasModifierProperty(PsiModifier
.FINAL
)) return null;
124 PsiType type
= getType();
125 // javac rejects all non primitive and non String constants, although JLS states constants "variables whose initializers are constant expressions"
126 if (!(type
instanceof PsiPrimitiveType
) && !type
.equalsToText("java.lang.String")) return null;
128 PsiExpression initializer
= getInitializer();
129 if (initializer
== null) return null;
130 return PsiConstantEvaluationHelperImpl
.computeCastTo(initializer
, getType(), visitedVars
);
133 public int getTextOffset() {
134 return getNameIdentifier().getTextOffset();
137 public void normalizeDeclaration() throws IncorrectOperationException
{
138 CheckUtil
.checkWritable(this);
139 final CharTable treeCharTab
= SharedImplUtil
.findCharTableByTree(this);
141 CompositeElement statement
= getTreeParent();
142 PsiElement
[] variables
= ((PsiDeclarationStatement
)SourceTreeToPsiMap
.treeElementToPsi(statement
)).getDeclaredElements();
143 if (variables
.length
> 1){
144 //CodeStyleManagerImpl codeStyleManager = (CodeStyleManagerImpl)getManager().getCodeStyleManager();
145 ASTNode last
= statement
;
146 for(int i
= 1; i
< variables
.length
; i
++){
147 ASTNode typeCopy
= getTypeElement().copy().getNode();
148 ASTNode modifierListCopy
= getModifierList().copy().getNode();
149 CompositeElement variable
= (CompositeElement
)SourceTreeToPsiMap
.psiElementToTree(variables
[i
]);
151 ASTNode comma
= TreeUtil
.skipElementsBack(variable
.getTreePrev(), StdTokenSets
.WHITE_SPACE_OR_COMMENT_BIT_SET
);
152 if (comma
!= null && comma
.getElementType() == JavaTokenType
.COMMA
){
153 CodeEditUtil
.removeChildren(statement
, comma
, variable
.getTreePrev());
156 CodeEditUtil
.removeChild(statement
, variable
);
157 final CharTable charTableByTree
= SharedImplUtil
.findCharTableByTree(statement
);
158 CompositeElement statement1
= Factory
.createCompositeElement(DECLARATION_STATEMENT
, charTableByTree
, getManager());
159 statement1
.addChild(variable
, null);
161 ASTNode space
= Factory
.createSingleLeafElement(JavaTokenType
.WHITE_SPACE
, " ", 0, 1, treeCharTab
, getManager());
162 variable
.addChild(space
, variable
.getFirstChildNode());
164 variable
.addChild(typeCopy
, variable
.getFirstChildNode());
166 if (modifierListCopy
.getTextLength() > 0){
167 space
= Factory
.createSingleLeafElement(JavaTokenType
.WHITE_SPACE
, " ", 0, 1, treeCharTab
, getManager());
168 variable
.addChild(space
, variable
.getFirstChildNode());
171 variable
.addChild(modifierListCopy
, variable
.getFirstChildNode());
173 ASTNode semicolon
= Factory
.createSingleLeafElement(JavaTokenType
.SEMICOLON
, ";", 0, 1, treeCharTab
, getManager());
174 SourceTreeToPsiMap
.psiElementToTree(variables
[i
- 1]).addChild(semicolon
, null);
176 CodeEditUtil
.addChild(statement
.getTreeParent(), statement1
, last
.getTreeNext());
179 //codeStyleManager.adjustInsertedCode(statement1);
184 JavaSharedImplUtil
.normalizeBrackets(this);
187 public void deleteChildInternal(@NotNull ASTNode child
) {
188 if (getChildRole(child
) == ChildRole
.INITIALIZER
){
189 ASTNode eq
= findChildByRole(ChildRole
.INITIALIZER_EQ
);
191 deleteChildInternal(eq
);
194 super.deleteChildInternal(child
);
197 public ASTNode
findChildByRole(int role
) {
198 LOG
.assertTrue(ChildRole
.isUnique(role
));
203 case ChildRole
.MODIFIER_LIST
:
204 return findChildByType(MODIFIER_LIST
);
207 return findChildByType(TYPE
);
210 return findChildByType(JavaTokenType
.IDENTIFIER
);
212 case ChildRole
.INITIALIZER_EQ
:
213 return findChildByType(JavaTokenType
.EQ
);
215 case ChildRole
.INITIALIZER
:
216 return findChildByType(ElementType
.EXPRESSION_BIT_SET
);
218 case ChildRole
.CLOSING_SEMICOLON
:
219 return TreeUtil
.findChildBackward(this, JavaTokenType
.SEMICOLON
);
223 public int getChildRole(ASTNode child
) {
224 LOG
.assertTrue(child
.getTreeParent() == this);
225 IElementType i
= child
.getElementType();
226 if (i
== MODIFIER_LIST
) {
227 return ChildRole
.MODIFIER_LIST
;
229 else if (i
== TYPE
) {
230 return getChildRole(child
, ChildRole
.TYPE
);
232 else if (i
== JavaTokenType
.IDENTIFIER
) {
233 return getChildRole(child
, ChildRole
.NAME
);
235 else if (i
== JavaTokenType
.EQ
) {
236 return getChildRole(child
, ChildRole
.INITIALIZER_EQ
);
238 else if (i
== JavaTokenType
.SEMICOLON
) {
239 return getChildRole(child
, ChildRole
.CLOSING_SEMICOLON
);
242 if (ElementType
.EXPRESSION_BIT_SET
.contains(child
.getElementType())) {
243 return ChildRole
.INITIALIZER
;
245 return ChildRoleBase
.NONE
;
249 public void accept(@NotNull PsiElementVisitor visitor
) {
250 if (visitor
instanceof JavaElementVisitor
) {
251 ((JavaElementVisitor
)visitor
).visitLocalVariable(this);
254 visitor
.visitElement(this);
258 public boolean processDeclarations(@NotNull PsiScopeProcessor processor
, @NotNull ResolveState state
, PsiElement lastParent
, @NotNull PsiElement place
) {
259 if (lastParent
== null) return true;
260 if (lastParent
.getContext() instanceof JavaDummyHolder
) {
261 return processor
.execute(this, state
);
264 if (lastParent
.getParent() != this) return true;
265 final ASTNode lastParentTree
= SourceTreeToPsiMap
.psiElementToTree(lastParent
);
267 return getChildRole(lastParentTree
) != ChildRole
.INITIALIZER
||
268 processor
.execute(this, state
);
271 public ItemPresentation
getPresentation() {
272 return JavaPresentationUtil
.getVariablePresentation(this);
275 public String
toString() {
276 return "PsiLocalVariable:" + getName();
280 public SearchScope
getUseScope() {
281 if (JspPsiUtil
.isInJspFile(this)) {
282 if (getTreeParent().getElementType() == JavaElementType
.DECLARATION_STATEMENT
&&
283 getTreeParent().getTreeParent() instanceof JspCodeBlock
&&
284 getTreeParent().getTreeParent().getTreeParent().getElementType() == JspElementType
.HOLDER_METHOD
) { //?
285 final JspFile jspFile
= JspPsiUtil
.getJspFile(this);
286 final JspContextManager contextManager
= JspContextManager
.getInstance(getProject());
287 if (contextManager
== null) {
288 return super.getUseScope();
291 final Set
<PsiFile
> allIncluded
= new THashSet
<PsiFile
>(10);
292 final JspFile rootContext
= contextManager
.getRootContextFile(jspFile
);
293 allIncluded
.add(rootContext
);
294 JspSpiUtil
.visitAllIncludedFilesRecursively(rootContext
, new Processor
<JspFile
>() {
295 public boolean process(final JspFile file
) {
296 allIncluded
.add(file
);
301 return new LocalSearchScope(allIncluded
.toArray(new PsiFile
[allIncluded
.size()]));
305 PsiElement parentElement
= getParent();
306 if (parentElement
instanceof PsiDeclarationStatement
) {
307 return new LocalSearchScope(parentElement
.getParent());
310 return getManager().getFileManager().getUseScope(this);
314 public Icon
getElementIcon(final int flags
) {
315 final RowIcon baseIcon
= createLayeredIcon(Icons
.VARIABLE_ICON
, ElementPresentationUtil
.getFlags(this, false));
316 return ElementPresentationUtil
.addVisibilityIcon(this, flags
, baseIcon
);
318 public PsiType
getTypeNoResolve() {