dfa: introduce ImplicitUsageProvider.isImplicitlyNotNullInitialized to support Mockito (IDEA-167790) in a way that doesn't break lombok (IDEA-170490)

This commit is contained in:
peter
2017-03-28 17:00:45 +02:00
parent 187223ef83
commit 99085fbe1c
5 changed files with 33 additions and 2 deletions
@@ -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;
@@ -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());
@@ -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;
}
}
@@ -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);
}
}
@@ -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);
}
}