From 0a17b195bb7c65f40ea128061c72d68fd1c7a9a8 Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Wed, 23 Feb 2011 21:04:24 +0100 Subject: [PATCH] Resource declaration and assignment conflicts highlighting --- .../analysis/HighlightControlFlowUtil.java | 15 +++-- .../psi/impl/source/PsiModifierListImpl.java | 58 ++++++++++--------- .../tree/java/PsiLocalVariableImpl.java | 8 +-- .../advHighlighting7/TryWithResources.java | 7 ++- .../TryWithResourcesWarn.java | 22 ++----- .../com/intellij/psi/JavaStubBuilderTest.java | 23 +------- .../intellij/psi/PsiScopedLocalVariable.java | 4 +- 7 files changed, 60 insertions(+), 77 deletions(-) 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 2288f318bdfc..83704c2c63be 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 @@ -674,25 +674,28 @@ public class HighlightControlFlowUtil { @Nullable public static PsiClass getInnerClassVariableReferencedFrom(PsiVariable variable, PsiElement context) { - PsiElement scope; + PsiElement[] scope; if (variable instanceof PsiScopedLocalVariable) { scope = ((PsiScopedLocalVariable)variable).getDeclarationScope(); } else if (variable instanceof PsiLocalVariable) { - scope = variable.getParent().getParent(); // code block or for statement + scope = new PsiElement[]{variable.getParent().getParent()}; // code block or for statement } else if (variable instanceof PsiParameter) { - scope = ((PsiParameter)variable).getDeclarationScope(); + scope = new PsiElement[]{((PsiParameter)variable).getDeclarationScope()}; } else { - scope = variable.getParent(); + scope = new PsiElement[]{variable.getParent()}; } - if (scope.getContainingFile() != context.getContainingFile()) return null; + if (scope.length < 1 || scope[0].getContainingFile() != context.getContainingFile()) return null; PsiElement parent = context.getParent(); PsiElement prevParent = context; + outer: while (parent != null) { - if (parent.equals(scope)) break; + for (PsiElement scopeElement : scope) { + if (parent.equals(scopeElement)) break outer; + } if (parent instanceof PsiClass && !(prevParent instanceof PsiExpressionList && parent instanceof PsiAnonymousClass)) { return (PsiClass)parent; } diff --git a/java/java-impl/src/com/intellij/psi/impl/source/PsiModifierListImpl.java b/java/java-impl/src/com/intellij/psi/impl/source/PsiModifierListImpl.java index fe99c2b043bf..e2329c6d3578 100644 --- a/java/java-impl/src/com/intellij/psi/impl/source/PsiModifierListImpl.java +++ b/java/java-impl/src/com/intellij/psi/impl/source/PsiModifierListImpl.java @@ -82,7 +82,7 @@ public class PsiModifierListImpl extends JavaStubPsiElement super(node); } - public boolean hasModifierProperty(@NotNull String name){ + public boolean hasModifierProperty(@NotNull String name) { final PsiModifierListStub stub = getStub(); if (stub != null) { int flag = NAME_TO_MODIFIER_FLAG_MAP.get(name); @@ -93,34 +93,34 @@ public class PsiModifierListImpl extends JavaStubPsiElement IElementType type = NAME_TO_KEYWORD_TYPE_MAP.get(name); PsiElement parent = getParent(); - if (parent instanceof PsiClass){ - PsiElement pparent = parent.getParent(); - if (pparent instanceof PsiClass && ((PsiClass)pparent).isInterface()){ - if (type == JavaTokenType.PUBLIC_KEYWORD){ + if (parent instanceof PsiClass) { + PsiElement grandParent = parent.getParent(); + if (grandParent instanceof PsiClass && ((PsiClass)grandParent).isInterface()) { + if (type == JavaTokenType.PUBLIC_KEYWORD) { return true; } - if (type == null){ // package local + if (type == null) { // package local return false; } - if (type == JavaTokenType.STATIC_KEYWORD){ + if (type == JavaTokenType.STATIC_KEYWORD) { return true; } } - if (((PsiClass)parent).isInterface()){ - if (type == JavaTokenType.ABSTRACT_KEYWORD){ + if (((PsiClass)parent).isInterface()) { + if (type == JavaTokenType.ABSTRACT_KEYWORD) { return true; } // nested interface is implicitly static - if (pparent instanceof PsiClass) { - if (type == JavaTokenType.STATIC_KEYWORD){ + if (grandParent instanceof PsiClass) { + if (type == JavaTokenType.STATIC_KEYWORD) { return true; } } } - if (((PsiClass)parent).isEnum()){ + if (((PsiClass)parent).isEnum()) { if (type == JavaTokenType.STATIC_KEYWORD) { - if (!(pparent instanceof PsiFile)) return true; + if (!(grandParent instanceof PsiFile)) return true; } else if (type == JavaTokenType.FINAL_KEYWORD) { final PsiField[] fields = ((PsiClass)parent).getFields(); @@ -138,37 +138,37 @@ public class PsiModifierListImpl extends JavaStubPsiElement } } } - else if (parent instanceof PsiMethod){ + else if (parent instanceof PsiMethod) { PsiClass aClass = ((PsiMethod)parent).getContainingClass(); - if (aClass != null && aClass.isInterface()){ - if (type == JavaTokenType.PUBLIC_KEYWORD){ + if (aClass != null && aClass.isInterface()) { + if (type == JavaTokenType.PUBLIC_KEYWORD) { return true; } - if (type == null){ // package local + if (type == null) { // package local return false; } - if (type == JavaTokenType.ABSTRACT_KEYWORD){ + if (type == JavaTokenType.ABSTRACT_KEYWORD) { return true; } } } - else if (parent instanceof PsiField){ + else if (parent instanceof PsiField) { if (parent instanceof PsiEnumConstant) { return type == JavaTokenType.PUBLIC_KEYWORD || type == JavaTokenType.STATIC_KEYWORD || type == JavaTokenType.FINAL_KEYWORD; } else { PsiClass aClass = ((PsiField)parent).getContainingClass(); - if (aClass != null && aClass.isInterface()){ - if (type == JavaTokenType.PUBLIC_KEYWORD){ + if (aClass != null && aClass.isInterface()) { + if (type == JavaTokenType.PUBLIC_KEYWORD) { return true; } - if (type == null){ // package local + if (type == null) { // package local return false; } - if (type == JavaTokenType.STATIC_KEYWORD){ + if (type == JavaTokenType.STATIC_KEYWORD) { return true; } - if (type == JavaTokenType.FINAL_KEYWORD){ + if (type == JavaTokenType.FINAL_KEYWORD) { return true; } } @@ -177,9 +177,15 @@ public class PsiModifierListImpl extends JavaStubPsiElement else if (parent instanceof PsiParameter) { if (type == JavaTokenType.FINAL_KEYWORD && ((PsiParameter)parent).getType() instanceof PsiDisjunctionType) return true; } + else if (parent instanceof PsiLocalVariable) { + PsiElement grandParent = parent.getParent(); + if (type == JavaTokenType.FINAL_KEYWORD && grandParent instanceof PsiResource) return true; + } - if (type == null){ // package local - return !hasModifierProperty(PsiModifier.PUBLIC) && !hasModifierProperty(PsiModifier.PRIVATE) && !hasModifierProperty(PsiModifier.PROTECTED); + if (type == null) { // package local + return !hasModifierProperty(PsiModifier.PUBLIC) && + !hasModifierProperty(PsiModifier.PRIVATE) && + !hasModifierProperty(PsiModifier.PROTECTED); } return getNode().findChildByType(type) != null; 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 af9a91209384..ad809cdf9ad3 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 @@ -280,18 +280,18 @@ public class PsiLocalVariableImpl extends CompositePsiElement implements PsiScop } @NotNull - public PsiElement getDeclarationScope() { + public PsiElement[] getDeclarationScope() { final PsiElement parentElement = getParent(); if (parentElement instanceof PsiDeclarationStatement) { - return parentElement.getParent(); + return new PsiElement[]{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 tryBlock != null ? new PsiElement[]{resourceList, tryBlock} : new PsiElement[]{resourceList}; } - return parentElement.getParent(); + return new PsiElement[]{parentElement.getParent()}; } @NotNull diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/TryWithResources.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/TryWithResources.java index 2a3875509b2f..fa8f950ef4b1 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/TryWithResources.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/TryWithResources.java @@ -37,7 +37,8 @@ class C { void m3(int p) throws Exception { try (MyResource r = new MyResource()) { r.doSomething(); - /* todo: < error descr="Cannot assign a value to final variable 'r'">r = null;*/ + r = null; + int r = 0; } catch (E e) { r = null; @@ -49,6 +50,10 @@ class C { try (MyResource r = new MyResource(); MyResource r = new MyResource()) { } + try (MyResource r1 = new MyResource(); MyResource r2 = r1) { } + + /* todo: try (MyResource r1 = < error descr="Cannot resolve symbol 'r'">r2; MyResource r2 = r1) { }*/ + MyResource r = null; try (MyResource r = new MyResource()) { } try (r = new MyResource()) { } diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/TryWithResourcesWarn.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/TryWithResourcesWarn.java index 7e72906b39d2..68b4fb4b4925 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/TryWithResourcesWarn.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/TryWithResourcesWarn.java @@ -27,24 +27,14 @@ class C { System.out.println(r1); } - try (MyResource r2 = new MyResource()) { - r2 = null; // todo: check for NPE - System.out.println(r2); - } + MyResource r2 = null; + System.out.println(r2); + try (r2 = new MyResource()) { } - MyResource r3 = null; - System.out.println(r3); - try (r3 = new MyResource()) { } + try (MyResource r3 = new MyResource()) { } - try (MyResource r4 = new MyResource()) { } - - try (MyResource r5 = new MyResource()) { - System.out.println(r5); - r5 = new MyResource(); - } - - MyResource r6; - try (MyResource r = r6) { + MyResource r4; + try (MyResource r = r4) { System.out.println(r); } } diff --git a/java/java-tests/testSrc/com/intellij/psi/JavaStubBuilderTest.java b/java/java-tests/testSrc/com/intellij/psi/JavaStubBuilderTest.java index 79d1c17fcc8f..3c3b631c413c 100644 --- a/java/java-tests/testSrc/com/intellij/psi/JavaStubBuilderTest.java +++ b/java/java-tests/testSrc/com/intellij/psi/JavaStubBuilderTest.java @@ -254,6 +254,7 @@ public class JavaStubBuilderTest extends LightIdeaTestCase { " void m() {\n" + " int local = 0;\n" + " for (int loop = 0; loop < 10; loop++) ;\n" + + " try (Resource r = new Resource()) { }\n" + " }\n" + "}", @@ -296,28 +297,6 @@ public class JavaStubBuilderTest extends LightIdeaTestCase { }); } - public void testNonMethodParameterLists() { - withLevel(LanguageLevel.JDK_1_7, new Runnable() { - @Override public void run() { - doTest("class C {\n" + - " {\n" + - " try (Resource r = new Resource()) { }\n" + - " }\n" + - "}", - - "PsiJavaFileStub []\n" + - " IMPORT_LIST:PsiImportListStub\n" + - " CLASS:PsiClassStub[name=C fqn=C]\n" + - " MODIFIER_LIST:PsiModifierListStub[mask=4096]\n" + - " TYPE_PARAMETER_LIST:PsiTypeParameterListStub\n" + - " EXTENDS_LIST:PsiRefListStub[EXTENDS_LIST:]\n" + - " IMPLEMENTS_LIST:PsiRefListStub[IMPLEMENTS_LIST:]\n" + - " CLASS_INITIALIZER:PsiClassInitializerStub\n" + - " MODIFIER_LIST:PsiModifierListStub[mask=4096]\n"); - } - }); - } - public void testSOEProof() { final StringBuilder sb = new StringBuilder(); final SecureRandom random = new SecureRandom(); diff --git a/java/openapi/src/com/intellij/psi/PsiScopedLocalVariable.java b/java/openapi/src/com/intellij/psi/PsiScopedLocalVariable.java index a3e629e79f49..b6f74359b683 100644 --- a/java/openapi/src/com/intellij/psi/PsiScopedLocalVariable.java +++ b/java/openapi/src/com/intellij/psi/PsiScopedLocalVariable.java @@ -19,10 +19,10 @@ 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. + * Returns the element or elements (method, "for" statement or try block) in which the variable is declared. * * @return the declaration scope for the variable. */ @NotNull - PsiElement getDeclarationScope(); + PsiElement[] getDeclarationScope(); }