mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Resource declaration and assignment conflicts highlighting
This commit is contained in:
+9
-6
@@ -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;
|
||||
}
|
||||
|
||||
@@ -82,7 +82,7 @@ public class PsiModifierListImpl extends JavaStubPsiElement<PsiModifierListStub>
|
||||
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<PsiModifierListStub>
|
||||
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<PsiModifierListStub>
|
||||
}
|
||||
}
|
||||
}
|
||||
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<PsiModifierListStub>
|
||||
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;
|
||||
|
||||
@@ -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
|
||||
|
||||
+6
-1
@@ -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</error >;*/
|
||||
<error descr="Cannot assign a value to final variable 'r'">r = null</error>;
|
||||
int <error descr="Variable 'r' is already defined in the scope">r</error> = 0;
|
||||
}
|
||||
catch (E e) {
|
||||
<error descr="Cannot resolve symbol 'r'">r</error> = null;
|
||||
@@ -49,6 +50,10 @@ class C {
|
||||
|
||||
try (MyResource <error descr="Variable 'r' is already defined in the scope">r</error> = new MyResource(); MyResource <error descr="Variable 'r' is already defined in the scope">r</error> = new MyResource()) { }
|
||||
|
||||
try (MyResource r1 = new MyResource(); MyResource r2 = r1) { }
|
||||
|
||||
/* todo: try (MyResource r1 = < error descr="Cannot resolve symbol 'r'">r2</error >; MyResource r2 = r1) { }*/
|
||||
|
||||
MyResource r = null;
|
||||
try (MyResource <error descr="Variable 'r' is already defined in the scope">r</error> = new MyResource()) { }
|
||||
try (r = new MyResource()) { }
|
||||
|
||||
+6
-16
@@ -27,24 +27,14 @@ class C {
|
||||
System.out.println(r1);
|
||||
}
|
||||
|
||||
try (MyResource r2 = <warning descr="Variable 'r2' initializer 'new MyResource()' is redundant">new MyResource()</warning>) {
|
||||
r2 = null; // todo: check for NPE
|
||||
System.out.println(r2);
|
||||
}
|
||||
MyResource r2 = null;
|
||||
System.out.println(r2);
|
||||
try (r2 = <warning descr="The value 'new MyResource()' assigned to r2 is never used">new MyResource()</warning>) { }
|
||||
|
||||
MyResource r3 = null;
|
||||
System.out.println(r3);
|
||||
try (r3 = <warning descr="The value 'new MyResource()' assigned to r3 is never used">new MyResource()</warning>) { }
|
||||
try (MyResource <warning descr="Variable 'r3' is never used">r3</warning> = new MyResource()) { }
|
||||
|
||||
try (MyResource <warning descr="Variable 'r4' is never used">r4</warning> = new MyResource()) { }
|
||||
|
||||
try (MyResource r5 = new MyResource()) {
|
||||
System.out.println(r5);
|
||||
r5 = <warning descr="The value 'new MyResource()' assigned to r5 is never used">new MyResource()</warning>;
|
||||
}
|
||||
|
||||
MyResource <warning descr="Variable 'r6' is never assigned">r6</warning>;
|
||||
try (MyResource r = <error descr="Variable 'r6' might not have been initialized">r6</error>) {
|
||||
MyResource <warning descr="Variable 'r4' is never assigned">r4</warning>;
|
||||
try (MyResource r = <error descr="Variable 'r4' might not have been initialized">r4</error>) {
|
||||
System.out.println(r);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user