From 99085fbe1ca7c074d5e2894e68c274d544c59f0d Mon Sep 17 00:00:00 2001 From: peter Date: Tue, 28 Mar 2017 16:07:58 +0200 Subject: [PATCH] dfa: introduce ImplicitUsageProvider.isImplicitlyNotNullInitialized to support Mockito (IDEA-167790) in a way that doesn't break lombok (IDEA-170490) --- .../dataFlow/value/DfaVariableValue.java | 10 ++++++++-- .../codeInspection/DataFlowInspectionTest.java | 5 +++++ .../codeInsight/daemon/ImplicitUsageProvider.java | 8 ++++++++ .../junit2/inspection/JUnitImplicitUsageProvider.java | 6 ++++++ .../binding/UIDesignerImplicitUsageProvider.java | 6 ++++++ 5 files changed, 33 insertions(+), 2 deletions(-) diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/value/DfaVariableValue.java b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/value/DfaVariableValue.java index d26173704f84..05c4bdd1babc 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/value/DfaVariableValue.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/value/DfaVariableValue.java @@ -24,10 +24,11 @@ */ package com.intellij.codeInspection.dataFlow.value; -import com.intellij.codeInsight.daemon.impl.UnusedSymbolUtil; +import com.intellij.codeInsight.daemon.ImplicitUsageProvider; import com.intellij.codeInsight.daemon.impl.analysis.JavaGenericsUtil; import com.intellij.codeInspection.dataFlow.DfaPsiUtil; import com.intellij.codeInspection.dataFlow.Nullness; +import com.intellij.openapi.extensions.Extensions; import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.Trinity; import com.intellij.patterns.ElementPattern; @@ -38,6 +39,7 @@ import com.intellij.psi.search.SearchScope; import com.intellij.psi.search.searches.ReferencesSearch; import com.intellij.psi.util.*; import com.intellij.util.SmartList; +import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.MultiMap; import com.siyeh.ig.psiutils.MethodUtils; import org.jetbrains.annotations.NotNull; @@ -229,10 +231,14 @@ public class DfaVariableValue extends DfaValue { private static boolean isOnlyImplicitlyInitialized(PsiField field) { return CachedValuesManager.getCachedValue(field, () -> CachedValueProvider.Result.create( - UnusedSymbolUtil.isImplicitWrite(field.getProject(), field, null) && weAreSureThereAreNoExplicitWrites(field), + isImplicitlyInitializedNotNull(field) && weAreSureThereAreNoExplicitWrites(field), PsiModificationTracker.MODIFICATION_COUNT)); } + private static boolean isImplicitlyInitializedNotNull(PsiField field) { + return ContainerUtil.exists(Extensions.getExtensions(ImplicitUsageProvider.EP_NAME), p -> p.isImplicitlyNotNullInitialized(field)); + } + private static boolean weAreSureThereAreNoExplicitWrites(PsiField field) { String name = field.getName(); if (name == null || field.getInitializer() != null) return false; diff --git a/java/java-tests/testSrc/com/intellij/codeInspection/DataFlowInspectionTest.java b/java/java-tests/testSrc/com/intellij/codeInspection/DataFlowInspectionTest.java index 927b58ab691f..666d3e139975 100644 --- a/java/java-tests/testSrc/com/intellij/codeInspection/DataFlowInspectionTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInspection/DataFlowInspectionTest.java @@ -446,6 +446,11 @@ public class DataFlowInspectionTest extends DataFlowInspectionTestCase { @Override public boolean isImplicitWrite(PsiElement element) { + return false; + } + + @Override + public boolean isImplicitlyNotNullInitialized(@NotNull PsiElement element) { return element instanceof PsiField && ((PsiField)element).getName().startsWith("field"); } }, myFixture.getTestRootDisposable()); diff --git a/platform/analysis-api/src/com/intellij/codeInsight/daemon/ImplicitUsageProvider.java b/platform/analysis-api/src/com/intellij/codeInsight/daemon/ImplicitUsageProvider.java index 5b9faa6af617..065e961c6287 100644 --- a/platform/analysis-api/src/com/intellij/codeInsight/daemon/ImplicitUsageProvider.java +++ b/platform/analysis-api/src/com/intellij/codeInsight/daemon/ImplicitUsageProvider.java @@ -18,6 +18,7 @@ package com.intellij.codeInsight.daemon; import com.intellij.openapi.extensions.ExtensionPointName; import com.intellij.psi.PsiElement; +import org.jetbrains.annotations.NotNull; /** * Allows to disable highlighting of certain elements as unused when such elements are not referenced @@ -36,4 +37,11 @@ public interface ImplicitUsageProvider { boolean isImplicitUsage(PsiElement element); boolean isImplicitRead(PsiElement element); boolean isImplicitWrite(PsiElement element); + + /** + * @return true if the given element is implicitly initialized to a non-null value + */ + default boolean isImplicitlyNotNullInitialized(@NotNull PsiElement element) { + return false; + } } diff --git a/plugins/junit/src/com/intellij/execution/junit2/inspection/JUnitImplicitUsageProvider.java b/plugins/junit/src/com/intellij/execution/junit2/inspection/JUnitImplicitUsageProvider.java index acb1ee747726..129e0f7d2c7d 100644 --- a/plugins/junit/src/com/intellij/execution/junit2/inspection/JUnitImplicitUsageProvider.java +++ b/plugins/junit/src/com/intellij/execution/junit2/inspection/JUnitImplicitUsageProvider.java @@ -20,6 +20,7 @@ import com.intellij.codeInsight.daemon.ImplicitUsageProvider; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiField; import com.intellij.psi.PsiParameter; +import org.jetbrains.annotations.NotNull; import java.util.Arrays; import java.util.List; @@ -50,4 +51,9 @@ public class JUnitImplicitUsageProvider implements ImplicitUsageProvider { } return element instanceof PsiField && AnnotationUtil.isAnnotated((PsiField) element, INJECTED_FIELD_ANNOTATIONS); } + + @Override + public boolean isImplicitlyNotNullInitialized(@NotNull PsiElement element) { + return isImplicitWrite(element); + } } diff --git a/plugins/ui-designer/src/com/intellij/uiDesigner/binding/UIDesignerImplicitUsageProvider.java b/plugins/ui-designer/src/com/intellij/uiDesigner/binding/UIDesignerImplicitUsageProvider.java index 8960f9de7b05..5bbbdf062e68 100644 --- a/plugins/ui-designer/src/com/intellij/uiDesigner/binding/UIDesignerImplicitUsageProvider.java +++ b/plugins/ui-designer/src/com/intellij/uiDesigner/binding/UIDesignerImplicitUsageProvider.java @@ -21,6 +21,7 @@ import com.intellij.psi.PsiElement; import com.intellij.psi.PsiField; import com.intellij.psi.PsiMethod; import com.intellij.uiDesigner.compiler.AsmCodeGenerator; +import org.jetbrains.annotations.NotNull; /** * @author yole @@ -45,4 +46,9 @@ public class UIDesignerImplicitUsageProvider implements ImplicitUsageProvider { public boolean isImplicitWrite(PsiElement element) { return element instanceof PsiField && FormReferenceProvider.getFormFile((PsiField)element) != null; } + + @Override + public boolean isImplicitlyNotNullInitialized(@NotNull PsiElement element) { + return isImplicitWrite(element); + } }