ensure non-initialized fields used inside lambdas are rejected if lambda is inside class initializer only (IDEA-154305)

This commit is contained in:
Anna.Kozlova
2016-04-07 15:13:00 +02:00
parent 66a8aa11b8
commit 0ed05632ff
3 changed files with 60 additions and 2 deletions
@@ -403,13 +403,32 @@ public class HighlightControlFlowUtil {
private static boolean inInnerClass(@NotNull PsiElement psiElement, @Nullable PsiClass containingClass, @NotNull PsiFile containingFile) {
PsiElement element = psiElement;
while (element != null) {
if (element instanceof PsiLambdaExpression) return false;
if (element instanceof PsiClass) return !containingFile.getManager().areElementsEquivalent(element, containingClass);
if (element instanceof PsiClass) {
final boolean innerClass = !containingFile.getManager().areElementsEquivalent(element, containingClass);
if (innerClass) {
final PsiLambdaExpression lambdaExpression = PsiTreeUtil.getParentOfType(psiElement, PsiLambdaExpression.class);
return lambdaExpression == null || !inLambdaInsideClassInitialization(containingClass, (PsiClass)element);
}
return false;
}
element = element.getParent();
}
return false;
}
private static boolean inLambdaInsideClassInitialization(@Nullable PsiClass containingClass, PsiClass aClass) {
PsiMember member = aClass;
while (member != null) {
if (member.getContainingClass() == containingClass) {
return member instanceof PsiField ||
member instanceof PsiMethod && ((PsiMethod)member).isConstructor() ||
member instanceof PsiClassInitializer;
}
member = PsiTreeUtil.getParentOfType(member, PsiMember.class, true);
}
return false;
}
public static boolean isReassigned(@NotNull PsiVariable variable,
@NotNull Map<PsiElement, Collection<ControlFlowUtil.VariableInfo>> finalVarProblems) {
if (variable instanceof PsiLocalVariable) {
@@ -0,0 +1,35 @@
class Test {
protected final String init;
protected final Runnable foo = new Runnable() {
{
Runnable r = () -> {
new Runnable() {
{
System.out.println(<error descr="Variable 'init' might not have been initialized">init</error>);
}
@Override
public void run() {
}
};
};
}
@Override
public void run() {
}
};
public Test(String init) {
this.init = init;
}
private void createClass() {
new Thread() {
{
Runnable runnable1 = () -> System.out.println(init);
}
};
}
}
@@ -300,6 +300,10 @@ public class NewLambdaHighlightingTest extends LightDaemonAnalyzerTestCase {
doTest();
}
public void testFieldReferencedFromLambdaInitializations() throws Exception {
doTest();
}
private void doTest() {
doTest(false);
}