mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
IDEA-156245 @NotNull doesn't seem to work for enums
This commit is contained in:
+32
-17
@@ -1474,7 +1474,7 @@ public class ControlFlowAnalyzer extends JavaElementVisitor {
|
||||
}
|
||||
|
||||
addConditionalRuntimeThrow();
|
||||
List<MethodContract> contracts = method instanceof PsiMethod ? getMethodCallContracts((PsiMethod)method, expression) : Collections.<MethodContract>emptyList();
|
||||
List<MethodContract> contracts = method instanceof PsiMethod ? getMethodCallContracts((PsiMethod)method, expression) : Collections.emptyList();
|
||||
addInstruction(new MethodCallInstruction(expression, myFactory.createValue(expression), contracts));
|
||||
if (!contracts.isEmpty()) {
|
||||
// if a contract resulted in 'fail', handle it
|
||||
@@ -1552,6 +1552,16 @@ public class ControlFlowAnalyzer extends JavaElementVisitor {
|
||||
return anno != null && Boolean.TRUE.equals(AnnotationUtil.getBooleanAttributeValue(anno, "pure"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitEnumConstant(PsiEnumConstant enumConstant) {
|
||||
if (enumConstant.getArgumentList() == null) return;
|
||||
|
||||
pushUnknown();
|
||||
pushConstructorArguments(enumConstant);
|
||||
addInstruction(new MethodCallInstruction(enumConstant, null, Collections.emptyList()));
|
||||
addInstruction(new PopInstruction());
|
||||
}
|
||||
|
||||
@Override public void visitNewExpression(PsiNewExpression expression) {
|
||||
startElement(expression);
|
||||
|
||||
@@ -1573,28 +1583,16 @@ public class ControlFlowAnalyzer extends JavaElementVisitor {
|
||||
}
|
||||
}
|
||||
addConditionalRuntimeThrow();
|
||||
addInstruction(new MethodCallInstruction(expression, null, Collections.<MethodContract>emptyList()));
|
||||
addInstruction(new MethodCallInstruction(expression, null, Collections.emptyList()));
|
||||
}
|
||||
else {
|
||||
final PsiExpressionList args = expression.getArgumentList();
|
||||
PsiMethod ctr = expression.resolveConstructor();
|
||||
if (args != null) {
|
||||
PsiExpression[] params = args.getExpressions();
|
||||
PsiParameter[] parameters = ctr == null ? null : ctr.getParameterList().getParameters();
|
||||
for (int i = 0; i < params.length; i++) {
|
||||
PsiExpression param = params[i];
|
||||
param.accept(this);
|
||||
if (parameters != null && i < parameters.length) {
|
||||
generateBoxingUnboxingInstructionFor(param, parameters[i].getType());
|
||||
}
|
||||
}
|
||||
}
|
||||
PsiMethod constructor = pushConstructorArguments(expression);
|
||||
|
||||
addConditionalRuntimeThrow();
|
||||
addInstruction(new MethodCallInstruction(expression, null, Collections.<MethodContract>emptyList()));
|
||||
addInstruction(new MethodCallInstruction(expression, null, Collections.emptyList()));
|
||||
|
||||
if (!myCatchStack.isEmpty()) {
|
||||
addMethodThrows(ctr, expression);
|
||||
addMethodThrows(constructor, expression);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1602,6 +1600,23 @@ public class ControlFlowAnalyzer extends JavaElementVisitor {
|
||||
finishElement(expression);
|
||||
}
|
||||
|
||||
private PsiMethod pushConstructorArguments(PsiConstructorCall call) {
|
||||
PsiExpressionList args = call.getArgumentList();
|
||||
PsiMethod ctr = call.resolveConstructor();
|
||||
if (args != null) {
|
||||
PsiExpression[] params = args.getExpressions();
|
||||
PsiParameter[] parameters = ctr == null ? null : ctr.getParameterList().getParameters();
|
||||
for (int i = 0; i < params.length; i++) {
|
||||
PsiExpression param = params[i];
|
||||
param.accept(this);
|
||||
if (parameters != null && i < parameters.length) {
|
||||
generateBoxingUnboxingInstructionFor(param, parameters[i].getType());
|
||||
}
|
||||
}
|
||||
}
|
||||
return ctr;
|
||||
}
|
||||
|
||||
@Override public void visitParenthesizedExpression(PsiParenthesizedExpression expression) {
|
||||
startElement(expression);
|
||||
PsiExpression inner = expression.getExpression();
|
||||
|
||||
@@ -158,7 +158,7 @@ public class DfaPsiUtil {
|
||||
return false;
|
||||
}
|
||||
|
||||
PsiCallExpression call = ((MethodCallInstruction)instruction).getCallExpression();
|
||||
PsiCall call = ((MethodCallInstruction)instruction).getCallExpression();
|
||||
if (call == null) return false;
|
||||
|
||||
if (call instanceof PsiMethodCallExpression &&
|
||||
|
||||
@@ -25,7 +25,6 @@ import com.intellij.psi.tree.IElementType;
|
||||
import com.intellij.psi.util.CachedValueProvider;
|
||||
import com.intellij.psi.util.CachedValuesManager;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.intellij.util.Function;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.containers.FList;
|
||||
@@ -113,7 +112,7 @@ public class DfaUtil {
|
||||
@Nullable
|
||||
static PsiElement getClosureInside(Instruction instruction) {
|
||||
if (instruction instanceof MethodCallInstruction) {
|
||||
PsiCallExpression anchor = ((MethodCallInstruction)instruction).getCallExpression();
|
||||
PsiCall anchor = ((MethodCallInstruction)instruction).getCallExpression();
|
||||
if (anchor instanceof PsiNewExpression) {
|
||||
return ((PsiNewExpression)anchor).getAnonymousClass();
|
||||
}
|
||||
|
||||
+2
-2
@@ -49,7 +49,7 @@ public class StandardInstructionVisitor extends InstructionVisitor {
|
||||
private final FactoryMap<MethodCallInstruction, Nullness> myReturnTypeNullability = new FactoryMap<MethodCallInstruction, Nullness>() {
|
||||
@Override
|
||||
protected Nullness create(MethodCallInstruction key) {
|
||||
final PsiCallExpression callExpression = key.getCallExpression();
|
||||
final PsiCall callExpression = key.getCallExpression();
|
||||
if (callExpression instanceof PsiNewExpression) {
|
||||
return Nullness.NOT_NULL;
|
||||
}
|
||||
@@ -237,7 +237,7 @@ public class StandardInstructionVisitor extends InstructionVisitor {
|
||||
@NotNull final DfaValue qualifier = memState.pop();
|
||||
boolean unboxing = instruction.getMethodType() == MethodCallInstruction.MethodType.UNBOXING;
|
||||
NullabilityProblem problem = unboxing ? NullabilityProblem.unboxingNullable : NullabilityProblem.callNPE;
|
||||
PsiExpression anchor = unboxing ? instruction.getContext() : instruction.getCallExpression();
|
||||
PsiElement anchor = unboxing ? instruction.getContext() : instruction.getCallExpression();
|
||||
if (!checkNotNullable(memState, qualifier, problem, anchor)) {
|
||||
forceNotNull(runner, memState, qualifier);
|
||||
}
|
||||
|
||||
+6
-6
@@ -37,11 +37,11 @@ import java.util.Map;
|
||||
|
||||
|
||||
public class MethodCallInstruction extends Instruction {
|
||||
@Nullable private final PsiCallExpression myCall;
|
||||
@Nullable private final PsiCall myCall;
|
||||
@Nullable private final PsiType myType;
|
||||
@NotNull private final PsiExpression[] myArgs;
|
||||
private final boolean myShouldFlushFields;
|
||||
@NotNull private final PsiExpression myContext;
|
||||
@NotNull private final PsiElement myContext;
|
||||
@Nullable private final PsiMethod myTargetMethod;
|
||||
private final List<MethodContract> myContracts;
|
||||
private final MethodType myMethodType;
|
||||
@@ -71,14 +71,14 @@ public class MethodCallInstruction extends Instruction {
|
||||
myArgRequiredNullability = Collections.emptyMap();
|
||||
}
|
||||
|
||||
public MethodCallInstruction(@NotNull PsiCallExpression call, @Nullable DfaValue precalculatedReturnValue, List<MethodContract> contracts) {
|
||||
public MethodCallInstruction(@NotNull PsiCall call, @Nullable DfaValue precalculatedReturnValue, List<MethodContract> contracts) {
|
||||
myContext = call;
|
||||
myContracts = contracts;
|
||||
myMethodType = MethodType.REGULAR_METHOD_CALL;
|
||||
myCall = call;
|
||||
final PsiExpressionList argList = call.getArgumentList();
|
||||
myArgs = argList != null ? argList.getExpressions() : PsiExpression.EMPTY_ARRAY;
|
||||
myType = myCall.getType();
|
||||
myType = myCall instanceof PsiCallExpression ? ((PsiCallExpression)myCall).getType() : null;
|
||||
|
||||
JavaResolveResult result = call.resolveMethodGenerics();
|
||||
myTargetMethod = (PsiMethod)result.getElement();
|
||||
@@ -175,12 +175,12 @@ public class MethodCallInstruction extends Instruction {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public PsiCallExpression getCallExpression() {
|
||||
public PsiCall getCallExpression() {
|
||||
return myCall;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public PsiExpression getContext() {
|
||||
public PsiElement getContext() {
|
||||
return myContext;
|
||||
}
|
||||
|
||||
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
import org.jetbrains.annotations.*;
|
||||
|
||||
enum NotNullEnum {
|
||||
ONE("One"),
|
||||
TWO(<warning descr="Passing 'null' argument to parameter annotated as @NotNull">null</warning>),
|
||||
THREE(<warning descr="Passing 'null' argument to parameter annotated as @NotNull">null</warning>) {};
|
||||
|
||||
private final @NotNull String param;
|
||||
NotNullEnum(@NotNull String param) {
|
||||
this.param = param;
|
||||
}
|
||||
@NotNull
|
||||
public String getParam() {
|
||||
return param;
|
||||
}
|
||||
public static void main(String[] args) {
|
||||
NotNullEnum one = ONE;
|
||||
}
|
||||
}
|
||||
@@ -84,6 +84,7 @@ public class DataFlowInspectionTest extends DataFlowInspectionTestCase {
|
||||
public void testEqualsEnumConstant() throws Throwable { doTest(); }
|
||||
public void testSwitchEnumConstant() { doTest(); }
|
||||
public void testEnumConstantNotNull() throws Throwable { doTest(); }
|
||||
public void testCheckEnumConstantConstructor() { doTest(); }
|
||||
public void testCompareToEnumConstant() throws Throwable { doTest(); }
|
||||
public void testEqualsConstant() throws Throwable { doTest(); }
|
||||
public void testDontSaveTypeValue() { doTest(); }
|
||||
|
||||
Reference in New Issue
Block a user