diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/defUse/DefUseInspectionBase.java b/java/java-analysis-impl/src/com/intellij/codeInspection/defUse/DefUseInspectionBase.java index cec0086a1378..8ddb38918106 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/defUse/DefUseInspectionBase.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/defUse/DefUseInspectionBase.java @@ -142,10 +142,12 @@ public class DefUseInspectionBase extends BaseJavaBatchLocalInspectionTool { final PsiClass psiClass = field.getContainingClass(); if (psiClass == null) return; final PsiClassInitializer[] classInitializers = psiClass.getInitializers(); - if (classInitializers.length == 0) return; - final boolean isStatic = field.hasModifierProperty(PsiModifier.STATIC); + final PsiMethod[] constructors = !isStatic ? psiClass.getConstructors() : PsiMethod.EMPTY_ARRAY; final boolean fieldHasInitializer = field.hasInitializer(); + final int maxPossibleWritesCount = classInitializers.length + (constructors.length != 0 ? 1 : 0) + (fieldHasInitializer ? 1 : 0); + if (maxPossibleWritesCount <= 1) return; + final PsiClassInitializer initializerBeforeField = PsiTreeUtil.getPrevSiblingOfType(field, PsiClassInitializer.class); final List fieldWrites = new ArrayList<>(); // class initializers and field initializer in the program order @@ -166,7 +168,7 @@ public class DefUseInspectionBase extends BaseJavaBatchLocalInspectionTool { } Collections.reverse(fieldWrites); - boolean wasDefinitelyAssigned = false; + boolean wasDefinitelyAssigned = isAssignedInAllConstructors(field, constructors); for (final FieldWrite fieldWrite : fieldWrites) { if (wasDefinitelyAssigned) { if (fieldWrite.isInitializer()) { @@ -184,10 +186,23 @@ public class DefUseInspectionBase extends BaseJavaBatchLocalInspectionTool { } } + private static boolean isAssignedInAllConstructors(@NotNull PsiField field, @NotNull PsiMethod[] constructors) { + if (constructors.length == 0 || field.hasModifierProperty(PsiModifier.STATIC)) { + return false; + } + for (PsiMethod constructor : constructors) { + final PsiCodeBlock body = constructor.getBody(); + if (body == null || !HighlightControlFlowUtil.variableDefinitelyAssignedIn(field, body)) { + return false; + } + } + return true; + } + @NotNull private static List collectAssignments(@NotNull PsiField field, @NotNull PsiClassInitializer classInitializer) { final List assignmentExpressions = new ArrayList<>(); - classInitializer.accept(new JavaRecursiveElementVisitor() { + classInitializer.accept(new JavaRecursiveElementWalkingVisitor() { @Override public void visitAssignmentExpression(PsiAssignmentExpression expression) { final PsiExpression lExpression = expression.getLExpression(); diff --git a/java/java-tests/testData/inspection/defUse/FieldInitializer.java b/java/java-tests/testData/inspection/defUse/FieldInitializer.java index 8bdc06ac46c8..0943af008ae1 100644 --- a/java/java-tests/testData/inspection/defUse/FieldInitializer.java +++ b/java/java-tests/testData/inspection/defUse/FieldInitializer.java @@ -42,6 +42,35 @@ class C { } { s = "d"; } } + static class C10 { + String s = "a"; + C10() { s = "b"; } + } + static class C11 { + String s = "a"; + C11() { s = "b"; } + C11(int i) { } + } + static class C12 { + String s = "a"; + C12() { s = "b"; } + C12(int i) { if (i == 0) s = "c"; } + } + static class C13 { + String s = "a"; + C13() { s = "b"; } + C13(int i) { if (i == 0) s = "c"; else s = "d"; } + } + static class C14 { + String s = "a"; + { s = "b"; } + C14() { s = "c"; } + } + static class C15 { + C15() { s = "c"; } + { if (b) s = "b"; } + String s = "a"; + } static class S1 { static { s = "a"; } @@ -88,4 +117,8 @@ class C { static String s = "a"; { s = "b"; } } + static class S11 { + static String s = "a"; + S11() { s = "b"; } + } } \ No newline at end of file