Basic test-suite for codeanalysis-annotations

GitOrigin-RevId: a134aead43faf095ac3ccec4fb24af23c8f241a7
This commit is contained in:
Tagir Valeev
2020-02-03 11:57:05 +07:00
committed by intellij-monorepo-bot
parent 1ecf89dcbf
commit 71300a36eb
12 changed files with 232 additions and 51 deletions

View File

@@ -7,11 +7,13 @@ import com.intellij.codeInsight.daemon.GroupNames;
import com.intellij.codeInsight.intention.AddAnnotationPsiFix;
import com.intellij.codeInsight.intention.impl.BaseIntentionAction;
import com.intellij.codeInspection.*;
import com.intellij.codeInspection.dataFlow.DataFlowInstructionVisitor.ConstantResult;
import com.intellij.codeInspection.dataFlow.NullabilityProblemKind.NullabilityProblem;
import com.intellij.codeInspection.dataFlow.fix.*;
import com.intellij.codeInspection.dataFlow.instructions.InstanceofInstruction;
import com.intellij.codeInspection.dataFlow.instructions.Instruction;
import com.intellij.codeInspection.dataFlow.types.DfType;
import com.intellij.codeInspection.dataFlow.types.DfTypes;
import com.intellij.codeInspection.dataFlow.value.DfaValue;
import com.intellij.codeInspection.nullable.NullableStuffInspectionBase;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
@@ -504,15 +506,15 @@ public abstract class DataFlowInspectionBase extends AbstractBaseJavaLocalInspec
return null;
}
private void reportNullabilityProblems(ProblemReporter reporter,
List<NullabilityProblem<?>> problems,
Map<PsiExpression, ConstantResult> expressions) {
protected void reportNullabilityProblems(ProblemReporter reporter,
List<NullabilityProblem<?>> problems,
Map<PsiExpression, ConstantResult> expressions) {
for (NullabilityProblem<?> problem : problems) {
PsiExpression expression = problem.getDereferencedExpression();
if (!REPORT_UNSOUND_WARNINGS) {
if (expression == null) continue;
PsiExpression unwrapped = PsiUtil.skipParenthesizedExprDown(expression);
if (!ExpressionUtils.isNullLiteral(unwrapped) && expressions.get(expression) != DataFlowInstructionVisitor.ConstantResult.NULL) {
if (!ExpressionUtils.isNullLiteral(unwrapped) && expressions.get(expression) != ConstantResult.NULL) {
continue;
}
}
@@ -1136,10 +1138,48 @@ public abstract class DataFlowInspectionBase extends AbstractBaseJavaLocalInspec
return SHORT_NAME;
}
protected enum ConstantResult {
TRUE, FALSE, NULL, UNKNOWN;
@NotNull
@Override
public String toString() {
return StringUtil.toLowerCase(name());
}
public Object value() {
switch (this) {
case TRUE:
return Boolean.TRUE;
case FALSE:
return Boolean.FALSE;
case NULL:
return null;
default:
throw new UnsupportedOperationException();
}
}
@NotNull
static ConstantResult fromDfType(@NotNull DfType dfType) {
if (dfType == DfTypes.NULL) return NULL;
if (dfType == DfTypes.TRUE) return TRUE;
if (dfType == DfTypes.FALSE) return FALSE;
return UNKNOWN;
}
@NotNull
static ConstantResult mergeValue(@Nullable ConstantResult state, @NotNull DfaMemoryState memState, @Nullable DfaValue value) {
if (state == UNKNOWN || value == null) return UNKNOWN;
ConstantResult nextState = fromDfType(memState.getUnboxedDfType(value));
return state == null || state == nextState ? nextState : UNKNOWN;
}
}
/**
* {@link ProblemsHolder} wrapper to avoid reporting two problems on the same anchor
*/
private static class ProblemReporter {
protected static class ProblemReporter {
private final Set<PsiElement> myReportedAnchors = new HashSet<>();
private final ProblemsHolder myHolder;
private final PsiElement myScope;
@@ -1149,7 +1189,7 @@ public abstract class DataFlowInspectionBase extends AbstractBaseJavaLocalInspec
myScope = scope;
}
void registerProblem(PsiElement element, String message, LocalQuickFix... fixes) {
public void registerProblem(PsiElement element, String message, LocalQuickFix... fixes) {
if (register(element)) {
myHolder.registerProblem(element, message, fixes);
}

View File

@@ -1,10 +1,10 @@
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.codeInspection.dataFlow;
import com.intellij.codeInspection.dataFlow.DataFlowInspectionBase.ConstantResult;
import com.intellij.codeInspection.dataFlow.instructions.*;
import com.intellij.codeInspection.dataFlow.types.DfConstantType;
import com.intellij.codeInspection.dataFlow.types.DfType;
import com.intellij.codeInspection.dataFlow.types.DfTypes;
import com.intellij.codeInspection.dataFlow.value.*;
import com.intellij.codeInspection.util.OptionalUtil;
import com.intellij.openapi.application.Application;
@@ -12,7 +12,6 @@ import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.*;
import com.intellij.psi.impl.PsiImplUtil;
import com.intellij.psi.util.PsiTreeUtil;
@@ -387,44 +386,6 @@ final class DataFlowInstructionVisitor extends StandardInstructionVisitor {
}
}
enum ConstantResult {
TRUE, FALSE, NULL, UNKNOWN;
@NotNull
@Override
public String toString() {
return StringUtil.toLowerCase(name());
}
public Object value() {
switch (this) {
case TRUE:
return Boolean.TRUE;
case FALSE:
return Boolean.FALSE;
case NULL:
return null;
default:
throw new UnsupportedOperationException();
}
}
@NotNull
static ConstantResult fromDfType(@NotNull DfType dfType) {
if (dfType == DfTypes.NULL) return NULL;
if (dfType == DfTypes.TRUE) return TRUE;
if (dfType == DfTypes.FALSE) return FALSE;
return UNKNOWN;
}
@NotNull
static ConstantResult mergeValue(@Nullable ConstantResult state, @NotNull DfaMemoryState memState, @Nullable DfaValue value) {
if (state == UNKNOWN || value == null) return UNKNOWN;
ConstantResult nextState = fromDfType(memState.getUnboxedDfType(value));
return state == null || state == nextState ? nextState : UNKNOWN;
}
}
static class ExpressionChunk {
final @NotNull PsiExpression myExpression;
final @Nullable TextRange myRange;

View File

@@ -179,7 +179,7 @@ public class NullabilityProblemKind<T extends PsiElement> {
else if (parent instanceof PsiReturnStatement) {
targetType = PsiTypesUtil.getMethodReturnType(parent);
}
if (targetType != null && !PsiType.VOID.equals(targetType)) {
if (targetType != null && !PsiType.VOID.equals(targetType) && DfaPsiUtil.getTypeNullability(targetType) != Nullability.NULLABLE) {
if (TypeConversionUtil.isPrimitiveAndNotNull(targetType)) {
return createUnboxingProblem(context, expression);
}
@@ -509,13 +509,13 @@ public class NullabilityProblemKind<T extends PsiElement> {
}
@NotNull
public String getMessage(Map<PsiExpression, DataFlowInstructionVisitor.ConstantResult> expressions) {
public String getMessage(Map<PsiExpression, DataFlowInspectionBase.ConstantResult> expressions) {
if (myKind.myAlwaysNullMessage == null || myKind.myNormalMessage == null) {
throw new IllegalStateException("This problem kind has no message associated: " + myKind);
}
PsiExpression expression = PsiUtil.skipParenthesizedExprDown(getDereferencedExpression());
if (expression != null) {
if (ExpressionUtils.isNullLiteral(expression) || expressions.get(expression) == DataFlowInstructionVisitor.ConstantResult.NULL) {
if (ExpressionUtils.isNullLiteral(expression) || expressions.get(expression) == DataFlowInspectionBase.ConstantResult.NULL) {
return myKind.myAlwaysNullMessage;
}
}