summaryrefslogtreecommitdiff
path: root/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/ContractInference.java
diff options
context:
space:
mode:
Diffstat (limited to 'java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/ContractInference.java')
-rw-r--r--java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/ContractInference.java38
1 files changed, 37 insertions, 1 deletions
diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/ContractInference.java b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/ContractInference.java
index bd207e58a0fe..7037fac8cfea 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/ContractInference.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/ContractInference.java
@@ -27,6 +27,7 @@ import com.intellij.psi.util.CachedValuesManager;
import com.intellij.util.Function;
import com.intellij.util.NullableFunction;
import com.intellij.util.containers.ContainerUtil;
+import com.siyeh.ig.psiutils.SideEffectChecker;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -213,6 +214,16 @@ class ContractInferenceInterpreter {
}
}
+ if (expr instanceof PsiNewExpression) {
+ return toContracts(states, NOT_NULL_VALUE);
+ }
+ if (expr instanceof PsiMethodCallExpression) {
+ PsiMethod method = ((PsiMethodCallExpression)expr).resolveMethod();
+ if (method != null && NullableNotNullManager.isNotNull(method)) {
+ return toContracts(states, NOT_NULL_VALUE);
+ }
+ }
+
final ValueConstraint constraint = getLiteralConstraint(expr);
if (constraint != null) {
return toContracts(states, constraint);
@@ -315,7 +326,7 @@ class ContractInferenceInterpreter {
private List<MethodContract> visitStatements(List<ValueConstraint[]> states, PsiStatement... statements) {
List<MethodContract> result = ContainerUtil.newArrayList();
for (PsiStatement statement : statements) {
- if (statement instanceof PsiBlockStatement && ((PsiBlockStatement)statement).getCodeBlock().getStatements().length == 1) {
+ if (statement instanceof PsiBlockStatement) {
result.addAll(visitStatements(states, ((PsiBlockStatement)statement).getCodeBlock().getStatements()));
}
else if (statement instanceof PsiIfStatement) {
@@ -353,12 +364,36 @@ class ContractInferenceInterpreter {
List<MethodContract> conditionResults = visitExpression(states, ((PsiAssertStatement)statement).getAssertCondition());
result.addAll(toContracts(antecedentsOf(filterReturning(conditionResults, FALSE_VALUE)), THROW_EXCEPTION));
}
+ else if (statement instanceof PsiDeclarationStatement && !mayHaveSideEffects((PsiDeclarationStatement)statement)) {
+ continue;
+ }
+ else if (statement instanceof PsiDoWhileStatement) {
+ result.addAll(visitStatements(states, ((PsiDoWhileStatement)statement).getBody()));
+ }
+ else if (statement instanceof PsiTryStatement) {
+ PsiCodeBlock block = ((PsiTryStatement)statement).getTryBlock();
+ if (block != null) {
+ result.addAll(visitStatements(states, block.getStatements()));
+ }
+ }
break; // visit only the first statement unless it's 'if' whose 'then' always returns and the next statement is effectively 'else'
}
return result;
}
+ private static boolean mayHaveSideEffects(PsiDeclarationStatement statement) {
+ for (PsiElement element : statement.getDeclaredElements()) {
+ if (element instanceof PsiVariable) {
+ PsiExpression initializer = ((PsiVariable)element).getInitializer();
+ if (initializer != null && SideEffectChecker.mayHaveSideEffects(initializer)) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
private static boolean alwaysReturns(@Nullable PsiStatement statement) {
if (statement instanceof PsiReturnStatement || statement instanceof PsiThrowStatement) return true;
if (statement instanceof PsiBlockStatement) {
@@ -381,6 +416,7 @@ class ContractInferenceInterpreter {
if (expr.textMatches(PsiKeyword.TRUE)) return TRUE_VALUE;
if (expr.textMatches(PsiKeyword.FALSE)) return FALSE_VALUE;
if (expr.textMatches(PsiKeyword.NULL)) return NULL_VALUE;
+ if (((PsiLiteralExpression)expr).getValue() instanceof String) return NOT_NULL_VALUE;
}
return null;
}