Java: Handle chained assignment of fields in class initializer (IDEA-188872)

This commit is contained in:
Pavel Dolgov
2018-04-02 13:27:24 +03:00
parent 3b316e01a7
commit 7ec424fabd
3 changed files with 36 additions and 0 deletions
@@ -140,6 +140,20 @@ public class DefUseInspectionBase extends AbstractBaseJavaLocalInspectionTool {
final List<PsiAssignmentExpression> assignments = collectAssignments(field, classInitializer);
if (!assignments.isEmpty()) {
boolean isDefinitely = HighlightControlFlowUtil.variableDefinitelyAssignedIn(field, classInitializer.getBody());
if (isDefinitely) {
try {
ControlFlow flow = HighlightControlFlowUtil.getControlFlowNoConstantEvaluate(classInitializer.getBody());
if (ControlFlowUtil.getReadBeforeWrite(flow)
.stream()
.anyMatch(read -> (isStatic || ExpressionUtil.isEffectivelyUnqualified(read)) &&
read.isReferenceTo(field))) {
isDefinitely = false;
}
}
catch (AnalysisCanceledException e) {
// ignore
}
}
fieldWrites.add(FieldWrite.createAssignments(isDefinitely, assignments));
}
}
@@ -0,0 +1,21 @@
import java.util.*;
class Base {
protected Base(Map<String, Class<?>> aMap) {
}
}
class SubClass extends Base {
private static Map<String, Class<?>> aMap = new TreeMap<>();
static {
aMap = Collections.unmodifiableMap(aMap);
}
public SubClass() { super(aMap); }
}
class WithStatic {
private static int n = 1;
static {
n = n + 1;
}
}
@@ -59,6 +59,7 @@ public class DefUseTest extends LightCodeInsightFixtureTestCase {
public void testNestedTryFinallyInEndlessLoop() { doTest(); }
public void testNestedTryFinallyInForLoop() { doTest(); }
public void testFieldInitializer() { doTest(); }
public void testChainedFieldInitializer() { doTest(); }
public void testFieldIgnoringRedundantInitializer() {
DefUseInspection inspection = new DefUseInspection();
inspection.REPORT_REDUNDANT_INITIALIZER = false;