final field initialization: don't treat anonymous args as inner classes (IDEA-168651)

This commit is contained in:
Anna.Kozlova
2017-03-06 10:18:16 +01:00
parent effcbfe27b
commit 5328c5fa2c
2 changed files with 75 additions and 6 deletions

View File

@@ -282,7 +282,7 @@ public class HighlightControlFlowUtil {
if (topBlock == null) return null;
final PsiElement parent = topBlock.getParent();
// access to final fields from inner classes always allowed
if (inInnerClass(expression, ((PsiField)variable).getContainingClass(),containingFile)) return null;
if (inInnerClass(expression, ((PsiField)variable).getContainingClass())) return null;
final PsiCodeBlock block;
final PsiClass aClass;
if (parent instanceof PsiMethod) {
@@ -401,14 +401,18 @@ public class HighlightControlFlowUtil {
return null;
}
private static boolean inInnerClass(@NotNull PsiElement psiElement, @Nullable PsiClass containingClass, @NotNull PsiFile containingFile) {
private static boolean inInnerClass(@NotNull PsiElement psiElement, @Nullable PsiClass containingClass) {
PsiElement element = psiElement;
while (element != null) {
if (element instanceof PsiClass) {
final boolean innerClass = !containingFile.getManager().areElementsEquivalent(element, containingClass);
final boolean innerClass = !psiElement.getManager().areElementsEquivalent(element, containingClass);
if (innerClass) {
if (element instanceof PsiAnonymousClass) {
return !(PsiTreeUtil.isAncestor(((PsiAnonymousClass)element).getArgumentList(), psiElement, false) ||
insideClassInitialization(containingClass, (PsiClass)element));
}
final PsiLambdaExpression lambdaExpression = PsiTreeUtil.getParentOfType(psiElement, PsiLambdaExpression.class);
return lambdaExpression == null || !inLambdaInsideClassInitialization(containingClass, (PsiClass)element);
return lambdaExpression == null || !insideClassInitialization(containingClass, (PsiClass)element);
}
return false;
}
@@ -417,7 +421,7 @@ public class HighlightControlFlowUtil {
return false;
}
private static boolean inLambdaInsideClassInitialization(@Nullable PsiClass containingClass, PsiClass aClass) {
private static boolean insideClassInitialization(@Nullable PsiClass containingClass, PsiClass aClass) {
PsiMember member = aClass;
while (member != null) {
if (member.getContainingClass() == containingClass) {

View File

@@ -234,7 +234,7 @@ class IDEA100237 {
}
final Object baz = new Object() {
final int qux = bar.<error descr="Cannot resolve method 'hashCode()'">hashCode</error>() + 1;
final int qux = <error descr="Variable 'bar' might not have been initialized">bar</error>.hashCode() + 1;
};
}
@@ -317,4 +317,69 @@ class StaticInitializedUsedInAnotherStaticField {
static {
STRINGS1 = "";
}
}
class InsideAnAnonymousClass {
static class Foo1 {
private final String _s;
public Foo1(String s) {
_s = s;
}
private final Bar _ss = new Bar(<error descr="Variable '_s' might not have been initialized">_s</error>) {
};
}
static class Foo2 {
private final String _s;
public Foo2(String s) {
_s = s;
}
private final Bar _ss = new Bar("") {
{
String inInitializer = <error descr="Variable '_s' might not have been initialized">_s</error>;
}
};
}
static class Foo3 {
private final String _s;
public Foo3(String s) {
_s = s;
}
private final Bar _ss = new Bar("") {
String inField = <error descr="Variable '_s' might not have been initialized">_s</error>;
void inMethod() {
String inMethodFoo = _s;
}
};
}
static class Foo4 {
private final String _s;
public Foo4(String s) {
_s = s;
}
private final Bar _ss = new Bar("") {
void inMethod() {
String inMethodFoo = _s;
}
};
}
static class Bar {
private final String _s;
public Bar(String s) {
_s = s;
}
}
}