update copyright
[fedora-idea.git] / java / java-impl / src / com / intellij / psi / impl / source / tree / java / PsiLocalVariableImpl.java
blob6c9680020c0af55f2ee9acbf90ca680f0e818f51
1 /*
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;
47 import javax.swing.*;
48 import java.util.Set;
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() {
60 super.clearCaches();
61 myCachedName = null;
64 @NotNull
65 public final PsiIdentifier getNameIdentifier() {
66 return (PsiIdentifier)findChildByRoleAsPsiElement(ChildRole.NAME);
69 @NotNull
70 public final String getName() {
71 String cachedName = myCachedName;
72 if (cachedName == null){
73 myCachedName = cachedName = getNameIdentifier().getText();
75 return cachedName;
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);
84 return this;
87 @NotNull
88 public final PsiType getType() {
89 return JavaSharedImplUtil.getType(this);
92 @NotNull
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);
180 last = 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);
190 if (eq != null){
191 deleteChildInternal(eq);
194 super.deleteChildInternal(child);
197 public ASTNode findChildByRole(int role) {
198 LOG.assertTrue(ChildRole.isUnique(role));
199 switch(role){
200 default:
201 return null;
203 case ChildRole.MODIFIER_LIST:
204 return findChildByType(MODIFIER_LIST);
206 case ChildRole.TYPE:
207 return findChildByType(TYPE);
209 case ChildRole.NAME:
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);
241 else {
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);
253 else {
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();
279 @NotNull
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);
297 return true;
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());
309 else {
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() {
319 return getType();