diff --git a/java/java-impl/src/com/intellij/codeInsight/ExceptionUtil.java b/java/java-impl/src/com/intellij/codeInsight/ExceptionUtil.java index a8a6f914ada4..ea1008c5fb32 100644 --- a/java/java-impl/src/com/intellij/codeInsight/ExceptionUtil.java +++ b/java/java-impl/src/com/intellij/codeInsight/ExceptionUtil.java @@ -22,7 +22,6 @@ import com.intellij.psi.*; import com.intellij.psi.controlFlow.*; import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.util.InheritanceUtil; -import com.intellij.psi.util.PsiUtil; import com.intellij.psi.util.TypeConversionUtil; import gnu.trove.THashSet; import org.jetbrains.annotations.NonNls; @@ -247,8 +246,8 @@ public class ExceptionUtil { unhandledExceptions = unhandled; } - if (PsiUtil.isResourceInTryStatement(element)) { - final PsiType resourceType = PsiUtil.getResourceType(element); + if (element instanceof PsiResource) { + final PsiType resourceType = ((PsiResource)element).getType(); if (resourceType instanceof PsiClassType) { final PsiClass resourceClass = ((PsiClassType)resourceType).resolve(); if (resourceClass != null) { diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightControlFlowUtil.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightControlFlowUtil.java index 9afe6a9b3815..2288f318bdfc 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightControlFlowUtil.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightControlFlowUtil.java @@ -13,15 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - -/* - * Created by IntelliJ IDEA. - * User: cdr - * Date: Aug 8, 2002 - * Time: 5:55:01 PM - * To change template for new class use - * Code Style | Class Templates options (Tools | IDE Options). - */ package com.intellij.codeInsight.daemon.impl.analysis; import com.intellij.codeInsight.daemon.JavaErrorMessages; @@ -43,9 +34,14 @@ import org.jetbrains.annotations.Nullable; import java.util.*; +/** + * @author cdr + * Date: Aug 8, 2002 + */ public class HighlightControlFlowUtil { private static final QuickFixFactory QUICK_FIX_FACTORY = QuickFixFactory.getInstance(); + private HighlightControlFlowUtil() { } @Nullable public static HighlightInfo checkMissingReturnStatement(PsiMethod method) { @@ -297,7 +293,7 @@ public class HighlightControlFlowUtil { topBlock = JspPsiUtil.isInJspFile(scope) && scope instanceof PsiFile ? scope : PsiUtil.getTopLevelEnclosingCodeBlock(expression, scope); if (variable instanceof PsiField) { - // non final field already initalized with default value + // non final field already initialized with default value if (!variable.hasModifierProperty(PsiModifier.FINAL)) return null; // final field may be initialized in ctor or class initializer only // if we're inside non-ctr method, skip it @@ -314,9 +310,9 @@ public class HighlightControlFlowUtil { if (parent instanceof PsiMethod) { PsiMethod constructor = (PsiMethod)parent; if (!parent.getManager().areElementsEquivalent(constructor.getContainingClass(), ((PsiField)variable).getContainingClass())) return null; - // static variables already initalized in class initalizers + // static variables already initialized in class initializers if (variable.hasModifierProperty(PsiModifier.STATIC)) return null; - // as a last chance, field may be initalized in this() call + // as a last chance, field may be initialized in this() call final List redirectedConstructors = getChainedConstructors(constructor); for (int j = 0; redirectedConstructors != null && j < redirectedConstructors.size(); j++) { PsiMethod redirectedConstructor = redirectedConstructors.get(j); @@ -338,7 +334,7 @@ public class HighlightControlFlowUtil { aClass = classInitializer.getContainingClass(); } else { - // field reference outside codeblock + // field reference outside code block // check variable initialized before its usage final PsiField field = (PsiField)variable; @@ -356,7 +352,7 @@ public class HighlightControlFlowUtil { && variableDefinitelyAssignedIn(variable, constructor.getBody())) { return null; } - // as a last chance, field may be initalized in this() call + // as a last chance, field may be initialized in this() call final List redirectedConstructors = getChainedConstructors(constructor); for (int j = 0; redirectedConstructors != null && j < redirectedConstructors.size(); j++) { PsiMethod redirectedConstructor = redirectedConstructors.get(j); @@ -371,13 +367,13 @@ public class HighlightControlFlowUtil { } if (aClass != null) { - // field may be initialized in class initalizer + // field may be initialized in class initializer final PsiClassInitializer[] initializers = aClass.getInitializers(); for (PsiClassInitializer initializer : initializers) { PsiCodeBlock body = initializer.getBody(); if (body == block) break; // variable referenced in initializer must be initialized in initializer preceding assignment - // varaibel refernced in field initializer or in class initializier + // variable referenced in field initializer or in class initializer boolean shouldCheckInitializerOrder = block == null || block.getParent() instanceof PsiClassInitializer; if (shouldCheckInitializerOrder && startOffset < initializer.getTextRange().getStartOffset()) continue; if (initializer.hasModifierProperty(PsiModifier.STATIC) @@ -449,6 +445,7 @@ public class HighlightControlFlowUtil { } + @Nullable public static HighlightInfo checkFinalVariableMightAlreadyHaveBeenAssignedTo(PsiVariable variable, PsiReferenceExpression expression, Map> finalVarProblems) { @@ -473,7 +470,7 @@ public class HighlightControlFlowUtil { final PsiField field = (PsiField)variable; final PsiClass aClass = field.getContainingClass(); if (aClass == null) return null; - // field can get assigned in other field inititializers + // field can get assigned in other field initializers final PsiField[] fields = aClass.getFields(); boolean isFieldStatic = field.hasModifierProperty(PsiModifier.STATIC); for (PsiField psiField : fields) { @@ -565,7 +562,8 @@ public class HighlightControlFlowUtil { } - public static HighlightInfo checkFinalVariableInitalizedInLoop(PsiReferenceExpression expression, PsiElement resolved) { + @Nullable + public static HighlightInfo checkFinalVariableInitializedInLoop(PsiReferenceExpression expression, PsiElement resolved) { if (ControlFlowUtil.isVariableAssignedInLoop(expression, resolved)) { String description = JavaErrorMessages.message("variable.assigned.in.loop", ((PsiVariable)resolved).getName()); final HighlightInfo highlightInfo = HighlightInfo.createHighlightInfo( @@ -580,6 +578,7 @@ public class HighlightControlFlowUtil { } + @Nullable public static HighlightInfo checkCannotWriteToFinal(PsiExpression expression) { PsiReferenceExpression reference = null; if (expression instanceof PsiAssignmentExpression) { @@ -659,6 +658,7 @@ public class HighlightControlFlowUtil { } + @Nullable static HighlightInfo checkVariableMustBeFinal(PsiVariable variable, PsiJavaCodeReferenceElement context) { if (variable.hasModifierProperty(PsiModifier.FINAL)) return null; final PsiClass innerClass = getInnerClassVariableReferencedFrom(variable, context); @@ -672,9 +672,13 @@ public class HighlightControlFlowUtil { return null; } + @Nullable public static PsiClass getInnerClassVariableReferencedFrom(PsiVariable variable, PsiElement context) { PsiElement scope; - if (variable instanceof PsiLocalVariable) { + if (variable instanceof PsiScopedLocalVariable) { + scope = ((PsiScopedLocalVariable)variable).getDeclarationScope(); + } + else if (variable instanceof PsiLocalVariable) { scope = variable.getParent().getParent(); // code block or for statement } else if (variable instanceof PsiParameter) { @@ -699,6 +703,7 @@ public class HighlightControlFlowUtil { } + @Nullable public static HighlightInfo checkInitializerCompleteNormally(PsiClassInitializer initializer) { final PsiCodeBlock body = initializer.getBody(); // unhandled exceptions already reported diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightUtil.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightUtil.java index 8368aec10784..8a02cbf32e83 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightUtil.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightUtil.java @@ -563,7 +563,7 @@ public class HighlightUtil { if (variable instanceof PsiLocalVariable || variable instanceof PsiParameter && ((PsiParameter)variable).getDeclarationScope() instanceof PsiCatchSection || variable instanceof PsiParameter && ((PsiParameter)variable).getDeclarationScope() instanceof PsiForeachStatement || - PsiUtil.isResourceInTryStatement(variable)) { + variable instanceof PsiResource && ((PsiResource)variable).getResourceElement() instanceof PsiLocalVariable) { PsiElement scope = PsiTreeUtil.getParentOfType(variable, PsiFile.class, PsiMethod.class, PsiClassInitializer.class); VariablesNotProcessor proc = new VariablesNotProcessor(variable, false) { protected boolean check(final PsiVariable var, final ResolveState state) { @@ -1118,8 +1118,8 @@ public class HighlightUtil { } @Nullable - public static HighlightInfo checkTryResourceIsAutoCloseable(@NotNull final PsiElement resource) { - final PsiType type = PsiUtil.getResourceType(resource); + public static HighlightInfo checkTryResourceIsAutoCloseable(@NotNull final PsiResource resource) { + final PsiType type = resource.getType(); if (type == null) return null; final PsiElementFactory factory = JavaPsiFacade.getInstance(resource.getProject()).getElementFactory(); diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java index 003e0d8e01a0..dfc4475f17e5 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java @@ -820,7 +820,7 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh if (!myHolder.hasErrorResults()) { myHolder.add(HighlightControlFlowUtil.checkFinalVariableMightAlreadyHaveBeenAssignedTo(variable, expression, myFinalVarProblems)); } - if (!myHolder.hasErrorResults()) myHolder.add(HighlightControlFlowUtil.checkFinalVariableInitalizedInLoop(expression, resolved)); + if (!myHolder.hasErrorResults()) myHolder.add(HighlightControlFlowUtil.checkFinalVariableInitializedInLoop(expression, resolved)); } } @@ -905,7 +905,7 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh PsiResourceList resources = statement.getResourceList(); if (resources != null) { - for (PsiElement resource : resources.getResources()) { + for (PsiResource resource : resources.getResources()) { myHolder.add(HighlightUtil.checkTryResourceIsAutoCloseable(resource)); } } diff --git a/java/java-impl/src/com/intellij/lang/java/parser/DeclarationParser.java b/java/java-impl/src/com/intellij/lang/java/parser/DeclarationParser.java index 018bbbc3c875..b162024dcd20 100644 --- a/java/java-impl/src/com/intellij/lang/java/parser/DeclarationParser.java +++ b/java/java-impl/src/com/intellij/lang/java/parser/DeclarationParser.java @@ -31,6 +31,7 @@ import org.jetbrains.annotations.Nullable; import static com.intellij.lang.PsiBuilderUtil.expect; import static com.intellij.lang.PsiBuilderUtil.nextTokenType; import static com.intellij.lang.java.parser.JavaParserUtil.*; +import static com.intellij.lang.java.parser.JavaParserUtil.exprType; public class DeclarationParser { @@ -588,12 +589,22 @@ public class DeclarationParser { } @Nullable - private static PsiBuilder.Marker parseResource(final PsiBuilder builder) { - PsiBuilder.Marker resource = parse(builder, Context.RESOURCE_LIST); - if (resource == null) { - resource = ExpressionParser.parse(builder); + public static PsiBuilder.Marker parseResource(final PsiBuilder builder) { + PsiBuilder.Marker element = parse(builder, Context.RESOURCE_LIST); + if (exprType(element) == JavaElementType.MODIFIER_LIST) { + return element; } - return resource; + else if (element == null) { + element = ExpressionParser.parse(builder); + } + + if (element != null) { + final PsiBuilder.Marker resource = element.precede(); + done(resource, JavaElementType.RESOURCE); + return resource; + } + + return null; } @Nullable diff --git a/java/java-impl/src/com/intellij/psi/impl/PsiImplUtil.java b/java/java-impl/src/com/intellij/psi/impl/PsiImplUtil.java index 2fa673130c31..0a863ea0d9a3 100644 --- a/java/java-impl/src/com/intellij/psi/impl/PsiImplUtil.java +++ b/java/java-impl/src/com/intellij/psi/impl/PsiImplUtil.java @@ -200,9 +200,10 @@ public class PsiImplUtil { final PsiElement lastParent) { final PsiResourceList resourceList = statement.getResourceList(); if (resourceList != null && lastParent instanceof PsiCodeBlock && lastParent == statement.getTryBlock()) { - final List resources = resourceList.getNamedResources(); - for (PsiLocalVariable resource : resources) { - if (!processor.execute(resource, state)) return false; + final List resources = resourceList.getResources(); + for (PsiResource resource : resources) { + final PsiElement resourceElement = resource.getResourceElement(); + if (resourceElement instanceof PsiLocalVariable && !processor.execute(resourceElement, state)) return false; } } diff --git a/java/java-impl/src/com/intellij/psi/impl/source/tree/JavaElementType.java b/java/java-impl/src/com/intellij/psi/impl/source/tree/JavaElementType.java index 7d31f4b1ff3a..593bb11d77c3 100644 --- a/java/java-impl/src/com/intellij/psi/impl/source/tree/JavaElementType.java +++ b/java/java-impl/src/com/intellij/psi/impl/source/tree/JavaElementType.java @@ -128,6 +128,7 @@ public interface JavaElementType { IElementType SYNCHRONIZED_STATEMENT = new JavaCompositeElementType("SYNCHRONIZED_STATEMENT", PsiSynchronizedStatementImpl.class); IElementType TRY_STATEMENT = new JavaCompositeElementType("TRY_STATEMENT", PsiTryStatementImpl.class); IElementType RESOURCE_LIST = new JavaCompositeElementType("RESOURCE_LIST", PsiResourceListImpl.class); + IElementType RESOURCE = new JavaCompositeElementType("RESOURCE", PsiResourceImpl.class); IElementType CATCH_SECTION = new JavaCompositeElementType("CATCH_SECTION", PsiCatchSectionImpl.class); IElementType LABELED_STATEMENT = new JavaCompositeElementType("LABELED_STATEMENT", PsiLabeledStatementImpl.class); IElementType ASSERT_STATEMENT = new JavaCompositeElementType("ASSERT_STATEMENT", PsiAssertStatementImpl.class); diff --git a/java/java-impl/src/com/intellij/psi/impl/source/tree/java/PsiLocalVariableImpl.java b/java/java-impl/src/com/intellij/psi/impl/source/tree/java/PsiLocalVariableImpl.java index 910c1f171773..af9a91209384 100644 --- a/java/java-impl/src/com/intellij/psi/impl/source/tree/java/PsiLocalVariableImpl.java +++ b/java/java-impl/src/com/intellij/psi/impl/source/tree/java/PsiLocalVariableImpl.java @@ -49,7 +49,7 @@ import org.jetbrains.annotations.NotNull; import javax.swing.*; import java.util.Set; -public class PsiLocalVariableImpl extends CompositePsiElement implements PsiLocalVariable, PsiVariableEx, Constants { +public class PsiLocalVariableImpl extends CompositePsiElement implements PsiScopedLocalVariable, PsiVariableEx, Constants { private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.source.tree.java.PsiLocalVariableImpl"); private volatile String myCachedName = null; @@ -279,6 +279,21 @@ public class PsiLocalVariableImpl extends CompositePsiElement implements PsiLoca return "PsiLocalVariable:" + getName(); } + @NotNull + public PsiElement getDeclarationScope() { + final PsiElement parentElement = getParent(); + if (parentElement instanceof PsiDeclarationStatement) { + return parentElement.getParent(); + } + else if (parentElement instanceof PsiResource) { + final PsiResourceList resourceList = (PsiResourceList)parentElement.getParent(); + final PsiTryStatement tryStatement = (PsiTryStatement)resourceList.getParent(); + final PsiCodeBlock tryBlock = tryStatement.getTryBlock(); + return tryBlock != null ? tryBlock : resourceList; + } + return parentElement.getParent(); + } + @NotNull public SearchScope getUseScope() { if (JspPsiUtil.isInJspFile(this)) { @@ -306,13 +321,8 @@ public class PsiLocalVariableImpl extends CompositePsiElement implements PsiLoca } final PsiElement parentElement = getParent(); - if (parentElement instanceof PsiDeclarationStatement) { - return new LocalSearchScope(parentElement.getParent()); - } - else if (parentElement instanceof PsiResourceList) { - final PsiElement tryStatement = parentElement.getParent(); - final PsiCodeBlock tryBlock = ((PsiTryStatement)tryStatement).getTryBlock(); - return new LocalSearchScope(tryBlock != null ? tryBlock : tryStatement); + if (parentElement instanceof PsiDeclarationStatement || parentElement instanceof PsiResource) { + return new LocalSearchScope(getDeclarationScope()); } else { return getManager().getFileManager().getUseScope(this); diff --git a/java/java-impl/src/com/intellij/psi/impl/source/tree/java/PsiResourceImpl.java b/java/java-impl/src/com/intellij/psi/impl/source/tree/java/PsiResourceImpl.java new file mode 100644 index 000000000000..35faa6a76cea --- /dev/null +++ b/java/java-impl/src/com/intellij/psi/impl/source/tree/java/PsiResourceImpl.java @@ -0,0 +1,74 @@ +/* + * Copyright 2000-2011 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.psi.impl.source.tree.java; + +import com.intellij.openapi.diagnostic.LogUtil; +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.psi.*; +import com.intellij.psi.impl.source.tree.CompositePsiElement; +import com.intellij.psi.impl.source.tree.JavaElementType; +import org.jetbrains.annotations.NotNull; + +public class PsiResourceImpl extends CompositePsiElement implements PsiResource { + private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.source.tree.java.PsiResourceImpl"); + + public PsiResourceImpl() { + super(JavaElementType.RESOURCE); + } + + @NotNull + @Override + public PsiElement getResourceElement() { + final PsiElement element = getFirstChild(); + assert element != null : this; + return element; + } + + @Override + public PsiType getType() { + final PsiElement element = getResourceElement(); + if (element instanceof PsiLocalVariable) { + return ((PsiLocalVariable)element).getType(); + } + else if (element instanceof PsiExpression) { + return ((PsiExpression)element).getType(); + } + LOG.error("Unexpected resource type: " + LogUtil.objectAndClass(element)); + return null; + } + + @Override + public void accept(@NotNull final PsiElementVisitor visitor) { + if (visitor instanceof JavaElementVisitor) { + ((JavaElementVisitor)visitor).visitResource(this); + } + else { + visitor.visitElement(this); + } + } + + public String getName() { + final PsiElement element = getResourceElement(); + if (element instanceof PsiLocalVariable) return ((PsiLocalVariable)element).getName(); + if (element instanceof PsiAssignmentExpression) return ((PsiAssignmentExpression)element).getLExpression().toString(); + return ""; + } + + @Override + public String toString() { + return "PsiResource:" + getName(); + } +} diff --git a/java/java-impl/src/com/intellij/psi/impl/source/tree/java/PsiResourceListImpl.java b/java/java-impl/src/com/intellij/psi/impl/source/tree/java/PsiResourceListImpl.java index f078c02d9514..f69d21569307 100644 --- a/java/java-impl/src/com/intellij/psi/impl/source/tree/java/PsiResourceListImpl.java +++ b/java/java-impl/src/com/intellij/psi/impl/source/tree/java/PsiResourceListImpl.java @@ -15,7 +15,10 @@ */ package com.intellij.psi.impl.source.tree.java; -import com.intellij.psi.*; +import com.intellij.psi.JavaElementVisitor; +import com.intellij.psi.PsiElementVisitor; +import com.intellij.psi.PsiResource; +import com.intellij.psi.PsiResourceList; import com.intellij.psi.impl.source.tree.CompositePsiElement; import com.intellij.psi.impl.source.tree.JavaElementType; import com.intellij.psi.util.PsiTreeUtil; @@ -30,15 +33,8 @@ public class PsiResourceListImpl extends CompositePsiElement implements PsiResou @NotNull @Override - public List getResources() { - //noinspection unchecked - return PsiTreeUtil.getChildrenOfAnyType(this, PsiExpression.class, PsiLocalVariable.class); - } - - @NotNull - @Override - public List getNamedResources() { - return PsiTreeUtil.getChildrenOfTypeAsList(this, PsiLocalVariable.class); + public List getResources() { + return PsiTreeUtil.getChildrenOfTypeAsList(this, PsiResource.class); } @Override diff --git a/java/java-tests/testData/psi/parser-partial/statements/TryIncomplete15.txt b/java/java-tests/testData/psi/parser-partial/statements/TryIncomplete15.txt index 297e7e00cfaf..5748458436f0 100644 --- a/java/java-tests/testData/psi/parser-partial/statements/TryIncomplete15.txt +++ b/java/java-tests/testData/psi/parser-partial/statements/TryIncomplete15.txt @@ -3,18 +3,19 @@ PsiJavaFile:TryIncomplete15.java PsiKeyword:try('try') PsiResourceList:(R r) PsiJavaToken:LPARENTH('(') - PsiLocalVariable:r - PsiModifierList: - - PsiTypeElement:R - PsiJavaCodeReferenceElement:R - PsiIdentifier:R('R') - PsiReferenceParameterList - - PsiWhiteSpace(' ') - PsiIdentifier:r('r') - PsiErrorElement:'=' expected - + PsiResource:r + PsiLocalVariable:r + PsiModifierList: + + PsiTypeElement:R + PsiJavaCodeReferenceElement:R + PsiIdentifier:R('R') + PsiReferenceParameterList + + PsiWhiteSpace(' ') + PsiIdentifier:r('r') + PsiErrorElement:'=' expected + PsiJavaToken:RPARENTH(')') PsiCodeBlock PsiJavaToken:LBRACE('{') diff --git a/java/java-tests/testData/psi/parser-partial/statements/TryIncomplete16.txt b/java/java-tests/testData/psi/parser-partial/statements/TryIncomplete16.txt index 4ed639c77577..e04ca47331f8 100644 --- a/java/java-tests/testData/psi/parser-partial/statements/TryIncomplete16.txt +++ b/java/java-tests/testData/psi/parser-partial/statements/TryIncomplete16.txt @@ -3,20 +3,21 @@ PsiJavaFile:TryIncomplete16.java PsiKeyword:try('try') PsiResourceList:(R r =) PsiJavaToken:LPARENTH('(') - PsiLocalVariable:r - PsiModifierList: - - PsiTypeElement:R - PsiJavaCodeReferenceElement:R - PsiIdentifier:R('R') - PsiReferenceParameterList - - PsiWhiteSpace(' ') - PsiIdentifier:r('r') - PsiWhiteSpace(' ') - PsiJavaToken:EQ('=') - PsiErrorElement:Expression expected - + PsiResource:r + PsiLocalVariable:r + PsiModifierList: + + PsiTypeElement:R + PsiJavaCodeReferenceElement:R + PsiIdentifier:R('R') + PsiReferenceParameterList + + PsiWhiteSpace(' ') + PsiIdentifier:r('r') + PsiWhiteSpace(' ') + PsiJavaToken:EQ('=') + PsiErrorElement:Expression expected + PsiJavaToken:RPARENTH(')') PsiCodeBlock PsiJavaToken:LBRACE('{') diff --git a/java/java-tests/testData/psi/parser-partial/statements/TryIncomplete17.txt b/java/java-tests/testData/psi/parser-partial/statements/TryIncomplete17.txt index 4a4aa969fceb..e4f111fb50c8 100644 --- a/java/java-tests/testData/psi/parser-partial/statements/TryIncomplete17.txt +++ b/java/java-tests/testData/psi/parser-partial/statements/TryIncomplete17.txt @@ -3,21 +3,22 @@ PsiJavaFile:TryIncomplete17.java PsiKeyword:try('try') PsiResourceList:(R r = 0;) PsiJavaToken:LPARENTH('(') - PsiLocalVariable:r - PsiModifierList: - - PsiTypeElement:R - PsiJavaCodeReferenceElement:R - PsiIdentifier:R('R') - PsiReferenceParameterList - - PsiWhiteSpace(' ') - PsiIdentifier:r('r') - PsiWhiteSpace(' ') - PsiJavaToken:EQ('=') - PsiWhiteSpace(' ') - PsiLiteralExpression:0 - PsiJavaToken:INTEGER_LITERAL('0') + PsiResource:r + PsiLocalVariable:r + PsiModifierList: + + PsiTypeElement:R + PsiJavaCodeReferenceElement:R + PsiIdentifier:R('R') + PsiReferenceParameterList + + PsiWhiteSpace(' ') + PsiIdentifier:r('r') + PsiWhiteSpace(' ') + PsiJavaToken:EQ('=') + PsiWhiteSpace(' ') + PsiLiteralExpression:0 + PsiJavaToken:INTEGER_LITERAL('0') PsiJavaToken:SEMICOLON(';') PsiErrorElement:Identifier or type expected diff --git a/java/java-tests/testData/psi/parser-partial/statements/TryNormal4.txt b/java/java-tests/testData/psi/parser-partial/statements/TryNormal4.txt index 0cf390a0fcbd..c3bec38b2bf4 100644 --- a/java/java-tests/testData/psi/parser-partial/statements/TryNormal4.txt +++ b/java/java-tests/testData/psi/parser-partial/statements/TryNormal4.txt @@ -3,21 +3,22 @@ PsiJavaFile:TryNormal4.java PsiKeyword:try('try') PsiResourceList:(R r = 0) PsiJavaToken:LPARENTH('(') - PsiLocalVariable:r - PsiModifierList: - - PsiTypeElement:R - PsiJavaCodeReferenceElement:R - PsiIdentifier:R('R') - PsiReferenceParameterList - - PsiWhiteSpace(' ') - PsiIdentifier:r('r') - PsiWhiteSpace(' ') - PsiJavaToken:EQ('=') - PsiWhiteSpace(' ') - PsiLiteralExpression:0 - PsiJavaToken:INTEGER_LITERAL('0') + PsiResource:r + PsiLocalVariable:r + PsiModifierList: + + PsiTypeElement:R + PsiJavaCodeReferenceElement:R + PsiIdentifier:R('R') + PsiReferenceParameterList + + PsiWhiteSpace(' ') + PsiIdentifier:r('r') + PsiWhiteSpace(' ') + PsiJavaToken:EQ('=') + PsiWhiteSpace(' ') + PsiLiteralExpression:0 + PsiJavaToken:INTEGER_LITERAL('0') PsiJavaToken:RPARENTH(')') PsiCodeBlock PsiJavaToken:LBRACE('{') diff --git a/java/java-tests/testData/psi/parser-partial/statements/TryNormal5.txt b/java/java-tests/testData/psi/parser-partial/statements/TryNormal5.txt index 8c11fdeff9ca..b69bed12f700 100644 --- a/java/java-tests/testData/psi/parser-partial/statements/TryNormal5.txt +++ b/java/java-tests/testData/psi/parser-partial/statements/TryNormal5.txt @@ -3,38 +3,40 @@ PsiJavaFile:TryNormal5.java PsiKeyword:try('try') PsiResourceList:(R1 r1 = 1; R2 r2 = 2) PsiJavaToken:LPARENTH('(') - PsiLocalVariable:r1 - PsiModifierList: - - PsiTypeElement:R1 - PsiJavaCodeReferenceElement:R1 - PsiIdentifier:R1('R1') - PsiReferenceParameterList - - PsiWhiteSpace(' ') - PsiIdentifier:r1('r1') - PsiWhiteSpace(' ') - PsiJavaToken:EQ('=') - PsiWhiteSpace(' ') - PsiLiteralExpression:1 - PsiJavaToken:INTEGER_LITERAL('1') + PsiResource:r1 + PsiLocalVariable:r1 + PsiModifierList: + + PsiTypeElement:R1 + PsiJavaCodeReferenceElement:R1 + PsiIdentifier:R1('R1') + PsiReferenceParameterList + + PsiWhiteSpace(' ') + PsiIdentifier:r1('r1') + PsiWhiteSpace(' ') + PsiJavaToken:EQ('=') + PsiWhiteSpace(' ') + PsiLiteralExpression:1 + PsiJavaToken:INTEGER_LITERAL('1') PsiJavaToken:SEMICOLON(';') PsiWhiteSpace(' ') - PsiLocalVariable:r2 - PsiModifierList: - - PsiTypeElement:R2 - PsiJavaCodeReferenceElement:R2 - PsiIdentifier:R2('R2') - PsiReferenceParameterList - - PsiWhiteSpace(' ') - PsiIdentifier:r2('r2') - PsiWhiteSpace(' ') - PsiJavaToken:EQ('=') - PsiWhiteSpace(' ') - PsiLiteralExpression:2 - PsiJavaToken:INTEGER_LITERAL('2') + PsiResource:r2 + PsiLocalVariable:r2 + PsiModifierList: + + PsiTypeElement:R2 + PsiJavaCodeReferenceElement:R2 + PsiIdentifier:R2('R2') + PsiReferenceParameterList + + PsiWhiteSpace(' ') + PsiIdentifier:r2('r2') + PsiWhiteSpace(' ') + PsiJavaToken:EQ('=') + PsiWhiteSpace(' ') + PsiLiteralExpression:2 + PsiJavaToken:INTEGER_LITERAL('2') PsiJavaToken:RPARENTH(')') PsiCodeBlock PsiJavaToken:LBRACE('{') diff --git a/java/java-tests/testData/psi/parser-partial/statements/TryNormal6.txt b/java/java-tests/testData/psi/parser-partial/statements/TryNormal6.txt index c82b04a42e85..bf1b0ed88fd3 100644 --- a/java/java-tests/testData/psi/parser-partial/statements/TryNormal6.txt +++ b/java/java-tests/testData/psi/parser-partial/statements/TryNormal6.txt @@ -3,10 +3,11 @@ PsiJavaFile:TryNormal6.java PsiKeyword:try('try') PsiResourceList:(r) PsiJavaToken:LPARENTH('(') - PsiReferenceExpression:r - PsiReferenceParameterList - - PsiIdentifier:r('r') + PsiResource: + PsiReferenceExpression:r + PsiReferenceParameterList + + PsiIdentifier:r('r') PsiJavaToken:RPARENTH(')') PsiCodeBlock PsiJavaToken:LBRACE('{') diff --git a/java/java-tests/testData/psi/parser-partial/statements/TryNormal7.txt b/java/java-tests/testData/psi/parser-partial/statements/TryNormal7.txt index 746ded3b71bb..1299595c7a9b 100644 --- a/java/java-tests/testData/psi/parser-partial/statements/TryNormal7.txt +++ b/java/java-tests/testData/psi/parser-partial/statements/TryNormal7.txt @@ -3,14 +3,16 @@ PsiJavaFile:TryNormal7.java PsiKeyword:try('try') PsiResourceList:(r; null) PsiJavaToken:LPARENTH('(') - PsiReferenceExpression:r - PsiReferenceParameterList - - PsiIdentifier:r('r') + PsiResource: + PsiReferenceExpression:r + PsiReferenceParameterList + + PsiIdentifier:r('r') PsiJavaToken:SEMICOLON(';') PsiWhiteSpace(' ') - PsiLiteralExpression:null - PsiJavaToken:NULL_KEYWORD('null') + PsiResource: + PsiLiteralExpression:null + PsiJavaToken:NULL_KEYWORD('null') PsiJavaToken:RPARENTH(')') PsiCodeBlock PsiJavaToken:LBRACE('{') diff --git a/java/openapi/src/com/intellij/psi/JavaElementVisitor.java b/java/openapi/src/com/intellij/psi/JavaElementVisitor.java index 6325cc5fcd59..c8162c6004b3 100644 --- a/java/openapi/src/com/intellij/psi/JavaElementVisitor.java +++ b/java/openapi/src/com/intellij/psi/JavaElementVisitor.java @@ -300,6 +300,10 @@ public abstract class JavaElementVisitor extends PsiElementVisitor { visitElement(resourceList); } + public void visitResource(PsiResource resource) { + visitElement(resource); + } + public void visitTypeElement(PsiTypeElement type) { visitElement(type); } diff --git a/java/openapi/src/com/intellij/psi/PsiResource.java b/java/openapi/src/com/intellij/psi/PsiResource.java new file mode 100644 index 000000000000..e53289079c86 --- /dev/null +++ b/java/openapi/src/com/intellij/psi/PsiResource.java @@ -0,0 +1,39 @@ +/* + * Copyright 2000-2011 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.psi; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +/** + * Represents a resource list of try-with-resources statement (automatic resource management) introduced in JDK 7. + * + * @see PsiResourceList#getResources() + * @since 10.5. + */ +public interface PsiResource extends PsiElement { + /** + * Returns main element of the resource. + * It may be PsiLocalVariable, PsiAssignmentExpression, or other instance of PsiExpression. + * + * @return resource element. + */ + @NotNull + PsiElement getResourceElement(); + + @Nullable + PsiType getType(); +} diff --git a/java/openapi/src/com/intellij/psi/PsiResourceList.java b/java/openapi/src/com/intellij/psi/PsiResourceList.java index 55b5cb12b863..c954ae7e79bd 100644 --- a/java/openapi/src/com/intellij/psi/PsiResourceList.java +++ b/java/openapi/src/com/intellij/psi/PsiResourceList.java @@ -26,19 +26,6 @@ import java.util.List; * @since 10.5. */ public interface PsiResourceList extends PsiElement { - /** - * Returns list of resource elements. Each element is either {@link PsiLocalVariable} or {@link PsiExpression}. - * - * @return list of resource elements. - */ @NotNull - List getResources(); - - /** - * Returns list of named resource elements only. - * - * @return list of named resource elements. - */ - @NotNull - List getNamedResources(); + List getResources(); } diff --git a/java/openapi/src/com/intellij/psi/PsiScopedLocalVariable.java b/java/openapi/src/com/intellij/psi/PsiScopedLocalVariable.java new file mode 100644 index 000000000000..a3e629e79f49 --- /dev/null +++ b/java/openapi/src/com/intellij/psi/PsiScopedLocalVariable.java @@ -0,0 +1,28 @@ +/* + * Copyright 2000-2011 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.psi; + +import org.jetbrains.annotations.NotNull; + +public interface PsiScopedLocalVariable extends PsiLocalVariable { + /** + * Returns the element (method, "for" statement or try block) in which the variable is declared. + * + * @return the declaration scope for the variable. + */ + @NotNull + PsiElement getDeclarationScope(); +} diff --git a/java/openapi/src/com/intellij/psi/util/PsiUtil.java b/java/openapi/src/com/intellij/psi/util/PsiUtil.java index de515c55ca48..12f0b759f1f8 100644 --- a/java/openapi/src/com/intellij/psi/util/PsiUtil.java +++ b/java/openapi/src/com/intellij/psi/util/PsiUtil.java @@ -15,7 +15,6 @@ */ package com.intellij.psi.util; -import com.intellij.openapi.diagnostic.LogUtil; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.roots.LanguageLevelProjectExtension; import com.intellij.openapi.util.Comparing; @@ -636,20 +635,6 @@ public final class PsiUtil extends PsiUtilBase { return PsiTreeUtil.getParentOfType(element, PsiDocComment.class, true) != null; } - public static boolean isResourceInTryStatement(final PsiElement element) { - return (element instanceof PsiLocalVariable || element instanceof PsiExpression) && - element.getParent() instanceof PsiResourceList; - } - - @Nullable - public static PsiType getResourceType(final PsiElement element) { - if (element == null || !(element.getParent() instanceof PsiResourceList)) return null; - if (element instanceof PsiLocalVariable) return ((PsiLocalVariable)element).getType(); - if (element instanceof PsiExpression) return ((PsiExpression)element).getType(); - LOG.error("Unexpected resource type: " + LogUtil.objectAndClass(element)); - return null; - } - private static class ParamWriteProcessor implements Processor { private volatile boolean myIsWriteRefFound = false; public boolean process(PsiReference reference) { diff --git a/platform/lang-api/src/com/intellij/psi/util/PsiTreeUtil.java b/platform/lang-api/src/com/intellij/psi/util/PsiTreeUtil.java index 91063c18bf59..92a835d850a4 100644 --- a/platform/lang-api/src/com/intellij/psi/util/PsiTreeUtil.java +++ b/platform/lang-api/src/com/intellij/psi/util/PsiTreeUtil.java @@ -312,22 +312,6 @@ public class PsiTreeUtil { return null; } - @NotNull - public static List getChildrenOfAnyType(@Nullable final PsiElement element, - @Nullable final Class... classes) { - if (element == null || classes == null || classes.length == 0) return Collections.emptyList(); - - final List result = new SmartList(); - for (PsiElement child = element.getFirstChild(); child != null; child = child.getNextSibling()) { - for (Class aClass : classes) { - if (aClass.isInstance(child)) { - result.add(child); - } - } - } - return result; - } - @Nullable public static T getNextSiblingOfType(@Nullable PsiElement sibling, @NotNull Class aClass) { if (sibling == null) return null;