dfa: support non-initialized final field escaping in constructors (IDEA-137154)

This commit is contained in:
peter
2015-03-23 18:57:36 +01:00
parent 4fc7acb38f
commit eab2402c47
3 changed files with 38 additions and 1 deletions
@@ -141,7 +141,8 @@ public class DataFlowInspectionBase extends BaseJavaBatchLocalInspectionTool {
PsiClass containingClass = PsiTreeUtil.getParentOfType(scope, PsiClass.class);
if (containingClass != null && PsiUtil.isLocalOrAnonymousClass(containingClass)) return;
final StandardDataFlowRunner dfaRunner = new StandardDataFlowRunner(TREAT_UNKNOWN_MEMBERS_AS_NULLABLE, true) {
final StandardDataFlowRunner dfaRunner = new StandardDataFlowRunner(TREAT_UNKNOWN_MEMBERS_AS_NULLABLE, !isInsideConstructorOrInitializer(
scope)) {
@Override
protected boolean shouldCheckTimeLimit() {
if (!onTheFly) return false;
@@ -151,6 +152,15 @@ public class DataFlowInspectionBase extends BaseJavaBatchLocalInspectionTool {
analyzeDfaWithNestedClosures(scope, holder, dfaRunner, Arrays.asList(dfaRunner.createMemoryState()), onTheFly);
}
private static boolean isInsideConstructorOrInitializer(PsiElement element) {
while (element != null) {
element = PsiTreeUtil.getParentOfType(element, PsiMethod.class, PsiClassInitializer.class);
if (element instanceof PsiClassInitializer) return true;
if (element instanceof PsiMethod && ((PsiMethod)element).isConstructor()) return true;
}
return false;
}
private void analyzeDfaWithNestedClosures(PsiElement scope,
ProblemsHolder holder,
StandardDataFlowRunner dfaRunner,
@@ -0,0 +1,26 @@
class SomeClass {
private final Object myField;
{
if (<error descr="Variable 'myField' might not have been initialized">myField</error> != null) { // false-positive report 'condition is always true'
System.out.println(myField.toString());
}
}
public SomeClass(SomeOtherClass o) {
o.invoke(new Runnable() {
public void run() {
if (myField != null) { // false-positive report 'condition is always true'
System.out.println(myField.toString());
}
}
});
myField = "xxx";
}
}
class SomeOtherClass {
public void invoke(Runnable r) {
r.run();
}
}
@@ -194,6 +194,7 @@ public class DataFlowInspectionTest extends LightCodeInsightFixtureTestCase {
public void testRememberLocalTransientFieldState() { doTest(); }
public void testFinalFieldDuringInitialization() { doTest(); }
public void testFinalFieldDuringSuperInitialization() { doTest(); }
public void testFinalFieldInConstructorAnonymous() { doTest(); }
public void _testSymmetricUncheckedCast() { doTest(); } // https://youtrack.jetbrains.com/issue/IDEABKL-6871
public void testNullCheckDoesntAffectUncheckedCast() { doTest(); }
public void testThrowNull() { doTest(); }