NullnessUtil#getExpressionNullness: useDataflow argument

This commit is contained in:
Tagir Valeev
2017-12-06 10:39:32 +07:00
parent 42193bb731
commit ab8419b387
4 changed files with 23 additions and 8 deletions
@@ -122,6 +122,18 @@ public class NullnessUtil {
}
public static Nullness getExpressionNullness(@Nullable PsiExpression expression) {
return getExpressionNullness(expression, false);
}
/**
* Tries to determine an expression nullness
*
* @param expression an expression to check
* @param useDataflow whether to use dataflow (more expensive, but may produce more precise result)
* @return expression nullness. UNKNOWN if unable to determine;
* NULLABLE if known to possibly have null value; NOT_NULL if definitely never null.
*/
public static Nullness getExpressionNullness(@Nullable PsiExpression expression, boolean useDataflow) {
expression = PsiUtil.skipParenthesizedExprDown(expression);
if (expression == null) return Nullness.UNKNOWN;
if (expression.textMatches(PsiKeyword.NULL)) return Nullness.NULLABLE;
@@ -136,13 +148,13 @@ public class NullnessUtil {
PsiExpression thenExpression = ((PsiConditionalExpression)expression).getThenExpression();
PsiExpression elseExpression = ((PsiConditionalExpression)expression).getElseExpression();
if (thenExpression == null || elseExpression == null) return Nullness.UNKNOWN;
Nullness left = getExpressionNullness(thenExpression);
Nullness left = getExpressionNullness(thenExpression, useDataflow);
if (left == Nullness.UNKNOWN) return Nullness.UNKNOWN;
Nullness right = getExpressionNullness(elseExpression);
Nullness right = getExpressionNullness(elseExpression, useDataflow);
return left == right ? left : Nullness.UNKNOWN;
}
if (expression instanceof PsiTypeCastExpression) {
return getExpressionNullness(((PsiTypeCastExpression)expression).getOperand());
return getExpressionNullness(((PsiTypeCastExpression)expression).getOperand(), useDataflow);
}
if (expression instanceof PsiReferenceExpression) {
PsiElement target = ((PsiReferenceExpression)expression).resolve();
@@ -151,10 +163,13 @@ public class NullnessUtil {
if (expression instanceof PsiAssignmentExpression) {
PsiAssignmentExpression assignment = (PsiAssignmentExpression)expression;
if(assignment.getOperationTokenType().equals(JavaTokenType.EQ)) {
return getExpressionNullness(assignment.getRExpression());
return getExpressionNullness(assignment.getRExpression(), useDataflow);
}
return Nullness.NOT_NULL;
}
if (useDataflow) {
return fromBoolean(CommonDataflow.getExpressionFact(expression, DfaFactType.CAN_BE_NULL));
}
if (expression instanceof PsiMethodCallExpression) {
PsiMethod method = ((PsiMethodCallExpression)expression).resolveMethod();
return method != null ? DfaPsiUtil.getElementNullability(expression.getType(), method) : Nullness.UNKNOWN;
@@ -51,7 +51,7 @@ public class OptionalPostfixTemplate extends StringBasedPostfixTemplate {
}
}
String methodName = Nullness.NOT_NULL.equals(NullnessUtil.getExpressionNullness((PsiExpression)element)) ? "of" : "ofNullable";
String methodName = Nullness.NOT_NULL.equals(NullnessUtil.getExpressionNullness((PsiExpression)element, true)) ? "of" : "ofNullable";
return "java.util." + className + "." + methodName + "($expr$)";
}
}
@@ -186,7 +186,7 @@ public class OptionalIsPresentInspection extends AbstractBaseJavaLocalInspection
if (!hasNoBadRefs) return ProblemType.NONE;
if (!hasOptionalReference.get() || !(lambdaCandidate instanceof PsiExpression)) return ProblemType.INFO;
PsiExpression expression = (PsiExpression)lambdaCandidate;
if (falseExpression != null && NullnessUtil.getExpressionNullness(expression) != Nullness.NOT_NULL) {
if (falseExpression != null && NullnessUtil.getExpressionNullness(expression, true) != Nullness.NOT_NULL) {
// falseExpression == null is "consumer" case (to be replaced with ifPresent()),
// in this case we don't care about expression nullness
return ProblemType.INFO;
@@ -292,7 +292,7 @@ public class ReplaceNullCheckInspection extends AbstractBaseJavaLocalInspectionT
nonNullDiff = qualifierDiff.getRight();
if(!ExpressionUtils.isReferenceTo(nullDiff, variable)) return null;
}
if(NullnessUtil.getExpressionNullness(nonNullDiff) != Nullness.NOT_NULL) return null;
if(NullnessUtil.getExpressionNullness(nonNullDiff, true) != Nullness.NOT_NULL) return null;
if(!LambdaGenerationUtil.canBeUncheckedLambda(nonNullDiff)) return null;
return new NotNullContext(nonNullDiff, nullDiff, nullBranch, variable, ifStatement, toDelete, false);
}
@@ -355,7 +355,7 @@ public class ReplaceNullCheckInspection extends AbstractBaseJavaLocalInspectionT
if(ClassUtils.isPrimitive(variable.getType())) return null;
PsiExpression nullBranch = negated ? ternary.getThenExpression() : ternary.getElseExpression();
if(!ExpressionUtils.isReferenceTo(nullBranch, variable)) return null;
if(NullnessUtil.getExpressionNullness(nonNullBranch) != Nullness.NOT_NULL) return null;
if(NullnessUtil.getExpressionNullness(nonNullBranch, true) != Nullness.NOT_NULL) return null;
if(!LambdaGenerationUtil.canBeUncheckedLambda(nonNullBranch)) return null;
return new TernaryNotNullContext(ternary, nonNullBranch, variable);
}