mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
DfaFactType improvements after review IDEA-CR-21121
1. DfaFactMap#calcFromVariable: unchecked warning fixed 2. NullnessUtil extracted out of CanBeNullFactType 3. CanBeNullFactType is anonymous now 4. New Nullness methods moved to NullnessUtil
This commit is contained in:
@@ -136,13 +136,10 @@ public final class DfaFactMap {
|
||||
* @return a calculated fact map.
|
||||
*/
|
||||
public static DfaFactMap calcFromVariable(@NotNull DfaVariableValue value) {
|
||||
DfaFactMap map = EMPTY;
|
||||
for (DfaFactType<?> type : DfaFactType.getTypes()) {
|
||||
@SuppressWarnings("unchecked")
|
||||
DfaFactType<Object> objectType = (DfaFactType<Object>)type;
|
||||
Object fact = objectType.calcFromVariable(value);
|
||||
map = map.with(objectType, fact);
|
||||
}
|
||||
return map;
|
||||
return StreamEx.of(DfaFactType.getTypes()).foldLeft(EMPTY, (factMap, type) -> updateMap(factMap, type, value));
|
||||
}
|
||||
|
||||
private static <T> DfaFactMap updateMap(DfaFactMap map, DfaFactType<T> factType, DfaVariableValue value) {
|
||||
return map.with(factType, factType.calcFromVariable(value));
|
||||
}
|
||||
}
|
||||
|
||||
+27
-152
@@ -15,23 +15,9 @@
|
||||
*/
|
||||
package com.intellij.codeInspection.dataFlow;
|
||||
|
||||
import com.intellij.codeInsight.daemon.ImplicitUsageProvider;
|
||||
import com.intellij.codeInsight.daemon.impl.analysis.JavaGenericsUtil;
|
||||
import com.intellij.codeInspection.dataFlow.rangeSet.LongRangeSet;
|
||||
import com.intellij.codeInspection.dataFlow.value.*;
|
||||
import com.intellij.openapi.extensions.Extensions;
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.patterns.ElementPattern;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.psi.search.PsiSearchHelper;
|
||||
import com.intellij.psi.search.SearchScope;
|
||||
import com.intellij.psi.search.searches.ReferencesSearch;
|
||||
import com.intellij.psi.util.CachedValueProvider;
|
||||
import com.intellij.psi.util.CachedValuesManager;
|
||||
import com.intellij.psi.util.PsiModificationTracker;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -39,10 +25,6 @@ import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import static com.intellij.patterns.PsiJavaPatterns.psiMember;
|
||||
import static com.intellij.patterns.PsiJavaPatterns.psiParameter;
|
||||
import static com.intellij.patterns.StandardPatterns.or;
|
||||
|
||||
/**
|
||||
* A type of the fact which restricts some value.
|
||||
*
|
||||
@@ -54,7 +36,33 @@ public abstract class DfaFactType<T> extends Key<T> {
|
||||
/**
|
||||
* This fact specifies whether the value can be null. The absence of the fact means that the nullability is unknown.
|
||||
*/
|
||||
public static final DfaFactType<Boolean> CAN_BE_NULL = new CanBeNullFactType();
|
||||
public static final DfaFactType<Boolean> CAN_BE_NULL = new DfaFactType<Boolean>("Can be null") {
|
||||
@Override
|
||||
String toString(Boolean fact) {
|
||||
return fact ? "Nullable" : "NotNull";
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
Boolean fromDfaValue(DfaValue value) {
|
||||
if (value instanceof DfaConstValue) {
|
||||
return ((DfaConstValue)value).getValue() == null;
|
||||
}
|
||||
if (value instanceof DfaBoxedValue || value instanceof DfaUnboxedValue || value instanceof DfaRangeValue) {
|
||||
return false;
|
||||
}
|
||||
if (value instanceof DfaTypeValue) {
|
||||
return NullnessUtil.toBoolean(((DfaTypeValue)value).getNullness());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
Boolean calcFromVariable(@NotNull DfaVariableValue value) {
|
||||
return NullnessUtil.calcCanBeNull(value);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* This fact is applied to the Optional values (like {@link java.util.Optional} or Guava Optional).
|
||||
@@ -159,137 +167,4 @@ public abstract class DfaFactType<T> extends Key<T> {
|
||||
static List<DfaFactType<?>> getTypes() {
|
||||
return Collections.unmodifiableList(ourFactTypes);
|
||||
}
|
||||
|
||||
private static class CanBeNullFactType extends DfaFactType<Boolean> {
|
||||
private static final ElementPattern<? extends PsiModifierListOwner> MEMBER_OR_METHOD_PARAMETER =
|
||||
or(psiMember(), psiParameter().withSuperParent(2, psiMember()));
|
||||
|
||||
private CanBeNullFactType() {super("Can be null");}
|
||||
|
||||
@Override
|
||||
String toString(Boolean fact) {
|
||||
return fact ? "Nullable" : "NotNull";
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
Boolean fromDfaValue(DfaValue value) {
|
||||
if (value instanceof DfaConstValue) {
|
||||
return ((DfaConstValue)value).getValue() == null;
|
||||
}
|
||||
if (value instanceof DfaBoxedValue || value instanceof DfaUnboxedValue || value instanceof DfaRangeValue) {
|
||||
return false;
|
||||
}
|
||||
if (value instanceof DfaTypeValue) {
|
||||
return ((DfaTypeValue)value).getNullness().toBoolean();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
Boolean calcFromVariable(@NotNull DfaVariableValue value) {
|
||||
PsiModifierListOwner var = value.getPsiVariable();
|
||||
Nullness nullability = DfaPsiUtil.getElementNullability(value.getVariableType(), var);
|
||||
if (nullability != Nullness.UNKNOWN) {
|
||||
return nullability.toBoolean();
|
||||
}
|
||||
|
||||
Nullness defaultNullability =
|
||||
value.getFactory().isUnknownMembersAreNullable() && MEMBER_OR_METHOD_PARAMETER.accepts(var) ? Nullness.NULLABLE : Nullness.UNKNOWN;
|
||||
|
||||
if (var instanceof PsiParameter && var.getParent() instanceof PsiForeachStatement) {
|
||||
PsiExpression iteratedValue = ((PsiForeachStatement)var.getParent()).getIteratedValue();
|
||||
if (iteratedValue != null) {
|
||||
PsiType itemType = JavaGenericsUtil.getCollectionItemType(iteratedValue);
|
||||
if (itemType != null) {
|
||||
return DfaPsiUtil.getElementNullability(itemType, var).toBoolean();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (var instanceof PsiField && value.getFactory().isHonorFieldInitializers()) {
|
||||
return getNullabilityFromFieldInitializers((PsiField)var, defaultNullability).toBoolean();
|
||||
}
|
||||
|
||||
return defaultNullability.toBoolean();
|
||||
}
|
||||
|
||||
private static Nullness getNullabilityFromFieldInitializers(PsiField field, Nullness defaultNullability) {
|
||||
if (DfaPsiUtil.isFinalField(field)) {
|
||||
PsiExpression initializer = field.getInitializer();
|
||||
if (initializer != null) {
|
||||
return getFieldInitializerNullness(initializer);
|
||||
}
|
||||
|
||||
List<PsiExpression> initializers = DfaPsiUtil.findAllConstructorInitializers(field);
|
||||
if (initializers.isEmpty()) {
|
||||
return defaultNullability;
|
||||
}
|
||||
|
||||
for (PsiExpression expression : initializers) {
|
||||
if (getFieldInitializerNullness(expression) == Nullness.NULLABLE) {
|
||||
return Nullness.NULLABLE;
|
||||
}
|
||||
}
|
||||
|
||||
if (DfaPsiUtil.isInitializedNotNull(field)) {
|
||||
return Nullness.NOT_NULL;
|
||||
}
|
||||
}
|
||||
else if (isOnlyImplicitlyInitialized(field)) {
|
||||
return Nullness.NOT_NULL;
|
||||
}
|
||||
return defaultNullability;
|
||||
}
|
||||
|
||||
private static boolean isOnlyImplicitlyInitialized(PsiField field) {
|
||||
return CachedValuesManager.getCachedValue(field, () -> CachedValueProvider.Result.create(
|
||||
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;
|
||||
|
||||
if (!isCheapEnoughToSearch(field, name)) return false;
|
||||
|
||||
return ReferencesSearch
|
||||
.search(field).forEach(
|
||||
reference -> reference instanceof PsiReferenceExpression && !PsiUtil.isAccessedForWriting((PsiReferenceExpression)reference));
|
||||
}
|
||||
|
||||
private static boolean isCheapEnoughToSearch(PsiField field, String name) {
|
||||
SearchScope scope = field.getUseScope();
|
||||
if (!(scope instanceof GlobalSearchScope)) return true;
|
||||
|
||||
PsiSearchHelper helper = PsiSearchHelper.SERVICE.getInstance(field.getProject());
|
||||
PsiSearchHelper.SearchCostResult result =
|
||||
helper.isCheapEnoughToSearch(name, (GlobalSearchScope)scope, field.getContainingFile(), null);
|
||||
return result != PsiSearchHelper.SearchCostResult.TOO_MANY_OCCURRENCES;
|
||||
}
|
||||
|
||||
private static Nullness getFieldInitializerNullness(@NotNull PsiExpression expression) {
|
||||
if (expression.textMatches(PsiKeyword.NULL)) return Nullness.NULLABLE;
|
||||
if (expression instanceof PsiNewExpression ||
|
||||
expression instanceof PsiLiteralExpression ||
|
||||
expression instanceof PsiPolyadicExpression) {
|
||||
return Nullness.NOT_NULL;
|
||||
}
|
||||
if (expression instanceof PsiReferenceExpression) {
|
||||
PsiElement target = ((PsiReferenceExpression)expression).resolve();
|
||||
return DfaPsiUtil.getElementNullability(expression.getType(), (PsiModifierListOwner)target);
|
||||
}
|
||||
if (expression instanceof PsiMethodCallExpression) {
|
||||
PsiMethod method = ((PsiMethodCallExpression)expression).resolveMethod();
|
||||
return method != null ? DfaPsiUtil.getElementNullability(expression.getType(), method) : Nullness.UNKNOWN;
|
||||
}
|
||||
return Nullness.UNKNOWN;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -283,7 +283,7 @@ public class DfaMemoryStateImpl implements DfaMemoryState {
|
||||
|
||||
private DfaVariableState withValueNullability(DfaValue value, DfaVariableState state) {
|
||||
if (value instanceof DfaTypeValue) {
|
||||
return state.withFact(DfaFactType.CAN_BE_NULL, ((DfaTypeValue)value).getNullness().toBoolean());
|
||||
return state.withFact(DfaFactType.CAN_BE_NULL, NullnessUtil.toBoolean(((DfaTypeValue)value).getNullness()));
|
||||
}
|
||||
if (isNull(value)) {
|
||||
return state.withFact(DfaFactType.CAN_BE_NULL, true);
|
||||
|
||||
+1
-1
@@ -174,7 +174,7 @@ class DfaVariableState {
|
||||
|
||||
@NotNull
|
||||
Nullness getNullability() {
|
||||
return Nullness.fromBoolean(myFactMap.get(DfaFactType.CAN_BE_NULL));
|
||||
return NullnessUtil.fromBoolean(myFactMap.get(DfaFactType.CAN_BE_NULL));
|
||||
}
|
||||
|
||||
public boolean isNotNull() {
|
||||
|
||||
@@ -15,33 +15,9 @@
|
||||
*/
|
||||
package com.intellij.codeInspection.dataFlow;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* @author cdr
|
||||
*/
|
||||
public enum Nullness {
|
||||
NOT_NULL, NULLABLE,UNKNOWN;
|
||||
|
||||
/**
|
||||
* Convert to boolean which is used to encode nullability in DfaFactType.CAN_BE_NULL
|
||||
*
|
||||
* @return TRUE if NULLABLE, FALSE if NOT_NULL, null if UNKNOWN
|
||||
*/
|
||||
@Nullable
|
||||
public Boolean toBoolean() {
|
||||
return this == UNKNOWN ? null : this == NULLABLE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert from boolean fact which is used to encode nullability in DfaFactType.CAN_BE_NULL
|
||||
*
|
||||
* @param fact TRUE if NULLABLE, FALSE if NOT_NULL, null if UNKNOWN
|
||||
* @return the corresponding nullness value
|
||||
*/
|
||||
@NotNull
|
||||
public static Nullness fromBoolean(@Nullable Boolean fact) {
|
||||
return fact == null ? UNKNOWN : fact ? NULLABLE : NOT_NULL;
|
||||
}
|
||||
NOT_NULL, NULLABLE,UNKNOWN
|
||||
}
|
||||
|
||||
@@ -0,0 +1,170 @@
|
||||
/*
|
||||
* Copyright 2000-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.codeInspection.dataFlow;
|
||||
|
||||
import com.intellij.codeInsight.daemon.ImplicitUsageProvider;
|
||||
import com.intellij.codeInsight.daemon.impl.analysis.JavaGenericsUtil;
|
||||
import com.intellij.codeInspection.dataFlow.value.DfaVariableValue;
|
||||
import com.intellij.openapi.extensions.Extensions;
|
||||
import com.intellij.patterns.ElementPattern;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.psi.search.PsiSearchHelper;
|
||||
import com.intellij.psi.search.SearchScope;
|
||||
import com.intellij.psi.search.searches.ReferencesSearch;
|
||||
import com.intellij.psi.util.CachedValueProvider;
|
||||
import com.intellij.psi.util.CachedValuesManager;
|
||||
import com.intellij.psi.util.PsiModificationTracker;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static com.intellij.patterns.PsiJavaPatterns.psiMember;
|
||||
import static com.intellij.patterns.PsiJavaPatterns.psiParameter;
|
||||
import static com.intellij.patterns.StandardPatterns.or;
|
||||
|
||||
public class NullnessUtil {
|
||||
private static final ElementPattern<? extends PsiModifierListOwner> MEMBER_OR_METHOD_PARAMETER =
|
||||
or(psiMember(), psiParameter().withSuperParent(2, psiMember()));
|
||||
|
||||
static Boolean calcCanBeNull(DfaVariableValue value) {
|
||||
PsiModifierListOwner var = value.getPsiVariable();
|
||||
Nullness nullability = DfaPsiUtil.getElementNullability(value.getVariableType(), var);
|
||||
if (nullability != Nullness.UNKNOWN) {
|
||||
return toBoolean(nullability);
|
||||
}
|
||||
|
||||
Nullness defaultNullability =
|
||||
value.getFactory().isUnknownMembersAreNullable() && MEMBER_OR_METHOD_PARAMETER.accepts(var) ? Nullness.NULLABLE : Nullness.UNKNOWN;
|
||||
|
||||
if (var instanceof PsiParameter && var.getParent() instanceof PsiForeachStatement) {
|
||||
PsiExpression iteratedValue = ((PsiForeachStatement)var.getParent()).getIteratedValue();
|
||||
if (iteratedValue != null) {
|
||||
PsiType itemType = JavaGenericsUtil.getCollectionItemType(iteratedValue);
|
||||
if (itemType != null) {
|
||||
return toBoolean(DfaPsiUtil.getElementNullability(itemType, var));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (var instanceof PsiField && value.getFactory().isHonorFieldInitializers()) {
|
||||
return toBoolean(getNullabilityFromFieldInitializers((PsiField)var, defaultNullability));
|
||||
}
|
||||
|
||||
return toBoolean(defaultNullability);
|
||||
}
|
||||
|
||||
private static Nullness getNullabilityFromFieldInitializers(PsiField field, Nullness defaultNullability) {
|
||||
if (DfaPsiUtil.isFinalField(field)) {
|
||||
PsiExpression initializer = field.getInitializer();
|
||||
if (initializer != null) {
|
||||
return getFieldInitializerNullness(initializer);
|
||||
}
|
||||
|
||||
List<PsiExpression> initializers = DfaPsiUtil.findAllConstructorInitializers(field);
|
||||
if (initializers.isEmpty()) {
|
||||
return defaultNullability;
|
||||
}
|
||||
|
||||
for (PsiExpression expression : initializers) {
|
||||
if (getFieldInitializerNullness(expression) == Nullness.NULLABLE) {
|
||||
return Nullness.NULLABLE;
|
||||
}
|
||||
}
|
||||
|
||||
if (DfaPsiUtil.isInitializedNotNull(field)) {
|
||||
return Nullness.NOT_NULL;
|
||||
}
|
||||
}
|
||||
else if (isOnlyImplicitlyInitialized(field)) {
|
||||
return Nullness.NOT_NULL;
|
||||
}
|
||||
return defaultNullability;
|
||||
}
|
||||
|
||||
private static boolean isOnlyImplicitlyInitialized(PsiField field) {
|
||||
return CachedValuesManager.getCachedValue(field, () -> CachedValueProvider.Result.create(
|
||||
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;
|
||||
|
||||
if (!isCheapEnoughToSearch(field, name)) return false;
|
||||
|
||||
return ReferencesSearch
|
||||
.search(field).forEach(
|
||||
reference -> reference instanceof PsiReferenceExpression && !PsiUtil.isAccessedForWriting((PsiReferenceExpression)reference));
|
||||
}
|
||||
|
||||
private static boolean isCheapEnoughToSearch(PsiField field, String name) {
|
||||
SearchScope scope = field.getUseScope();
|
||||
if (!(scope instanceof GlobalSearchScope)) return true;
|
||||
|
||||
PsiSearchHelper helper = PsiSearchHelper.SERVICE.getInstance(field.getProject());
|
||||
PsiSearchHelper.SearchCostResult result =
|
||||
helper.isCheapEnoughToSearch(name, (GlobalSearchScope)scope, field.getContainingFile(), null);
|
||||
return result != PsiSearchHelper.SearchCostResult.TOO_MANY_OCCURRENCES;
|
||||
}
|
||||
|
||||
private static Nullness getFieldInitializerNullness(@NotNull PsiExpression expression) {
|
||||
if (expression.textMatches(PsiKeyword.NULL)) return Nullness.NULLABLE;
|
||||
if (expression instanceof PsiNewExpression ||
|
||||
expression instanceof PsiLiteralExpression ||
|
||||
expression instanceof PsiPolyadicExpression) {
|
||||
return Nullness.NOT_NULL;
|
||||
}
|
||||
if (expression instanceof PsiReferenceExpression) {
|
||||
PsiElement target = ((PsiReferenceExpression)expression).resolve();
|
||||
return DfaPsiUtil.getElementNullability(expression.getType(), (PsiModifierListOwner)target);
|
||||
}
|
||||
if (expression instanceof PsiMethodCallExpression) {
|
||||
PsiMethod method = ((PsiMethodCallExpression)expression).resolveMethod();
|
||||
return method != null ? DfaPsiUtil.getElementNullability(expression.getType(), method) : Nullness.UNKNOWN;
|
||||
}
|
||||
return Nullness.UNKNOWN;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert from boolean fact which is used to encode nullability in DfaFactType.CAN_BE_NULL
|
||||
*
|
||||
* @param fact TRUE if NULLABLE, FALSE if NOT_NULL, null if UNKNOWN
|
||||
* @return the corresponding nullness value
|
||||
*/
|
||||
@NotNull
|
||||
public static Nullness fromBoolean(@Nullable Boolean fact) {
|
||||
return fact == null ? Nullness.UNKNOWN : fact ? Nullness.NULLABLE : Nullness.NOT_NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert nullness to boolean which is used to encode nullability in DfaFactType.CAN_BE_NULL
|
||||
*
|
||||
* @return TRUE if NULLABLE, FALSE if NOT_NULL, null if UNKNOWN
|
||||
*/
|
||||
@Nullable
|
||||
public static Boolean toBoolean(@NotNull Nullness nullness) {
|
||||
return nullness == Nullness.UNKNOWN ? null : nullness == Nullness.NULLABLE;
|
||||
}
|
||||
}
|
||||
+2
-5
@@ -16,10 +16,7 @@
|
||||
|
||||
package com.intellij.codeInspection.dataFlow.value;
|
||||
|
||||
import com.intellij.codeInspection.dataFlow.DfaFactMap;
|
||||
import com.intellij.codeInspection.dataFlow.DfaFactType;
|
||||
import com.intellij.codeInspection.dataFlow.Nullness;
|
||||
import com.intellij.codeInspection.dataFlow.SpecialField;
|
||||
import com.intellij.codeInspection.dataFlow.*;
|
||||
import com.intellij.openapi.util.Comparing;
|
||||
import com.intellij.openapi.util.Trinity;
|
||||
import com.intellij.psi.*;
|
||||
@@ -156,7 +153,7 @@ public class DfaVariableValue extends DfaValue {
|
||||
|
||||
@NotNull
|
||||
public Nullness getInherentNullability() {
|
||||
return Nullness.fromBoolean(getInherentFacts().get(DfaFactType.CAN_BE_NULL));
|
||||
return NullnessUtil.fromBoolean(getInherentFacts().get(DfaFactType.CAN_BE_NULL));
|
||||
}
|
||||
|
||||
public boolean isFlushableByCalls() {
|
||||
|
||||
Reference in New Issue
Block a user