From ca5da73932d54e98fd57a7d7c2e964cd89a87d0e Mon Sep 17 00:00:00 2001 From: Tagir Valeev Date: Mon, 11 Jan 2021 11:02:58 +0700 Subject: [PATCH] [java-dfa] Do not report variable is already assigned to this value for final field assignments (IDEA-258765) GitOrigin-RevId: 0820f165cacbde79ced969d1ca8f1ba5910c99d6 --- .../dataFlow/DataFlowInspectionBase.java | 26 ++++++++++++------- .../dataFlow/fixture/RedundantAssignment.java | 9 +++++++ 2 files changed, 25 insertions(+), 10 deletions(-) diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DataFlowInspectionBase.java b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DataFlowInspectionBase.java index 6e70179e7f86..83bee52049cd 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DataFlowInspectionBase.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DataFlowInspectionBase.java @@ -528,16 +528,22 @@ public abstract class DataFlowInspectionBase extends AbstractBaseJavaLocalInspec if (context instanceof PsiForStatement && PsiTreeUtil.isAncestor(((PsiForStatement)context).getInitialization(), expr, true)) { return; } - if (context instanceof PsiClassInitializer && expr instanceof PsiReferenceExpression) { - if (assignment != null) { - Object constValue = ExpressionUtils.computeConstantExpression(assignment.getRExpression()); - if (constValue == PsiTypesUtil.getDefaultValue(expr.getType())) { - PsiReferenceExpression ref = (PsiReferenceExpression)expr; - PsiElement target = ref.resolve(); - if (target instanceof PsiField && - (((PsiField)target).hasModifierProperty(PsiModifier.STATIC) || ExpressionUtil.isEffectivelyUnqualified(ref)) && - ((PsiField)target).getContainingClass() == ((PsiClassInitializer)context).getContainingClass()) { - return; + if (expr instanceof PsiReferenceExpression) { + PsiReferenceExpression ref = (PsiReferenceExpression)expr; + PsiField field = tryCast(ref.resolve(), PsiField.class); + if (field != null) { + // Final field assignment: even if redundant according to DFA model (e.g. this.field = null), + // it's necessary due to language semantics + if (field.hasModifierProperty(PsiModifier.FINAL)) return; + if (context instanceof PsiClassInitializer) { + if (assignment != null) { + Object constValue = ExpressionUtils.computeConstantExpression(assignment.getRExpression()); + if (constValue == PsiTypesUtil.getDefaultValue(expr.getType())) { + if ((field.hasModifierProperty(PsiModifier.STATIC) || ExpressionUtil.isEffectivelyUnqualified(ref)) && + field.getContainingClass() == ((PsiClassInitializer)context).getContainingClass()) { + return; + } + } } } } diff --git a/java/java-tests/testData/inspection/dataFlow/fixture/RedundantAssignment.java b/java/java-tests/testData/inspection/dataFlow/fixture/RedundantAssignment.java index 29677c1e0cbf..3f702ab8d438 100644 --- a/java/java-tests/testData/inspection/dataFlow/fixture/RedundantAssignment.java +++ b/java/java-tests/testData/inspection/dataFlow/fixture/RedundantAssignment.java @@ -76,3 +76,12 @@ class TestConstant { x = NONE; } } +// IDEA-258765 +interface Intersection { + interface I { } + final class A { } + class Data { + final T value; + private Data(T value) { this.value = value; } + } +} \ No newline at end of file