mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
DFA: separate warning to store into notnull array; fixes for assignment
Review ID: IDEA-CR-24027
This commit is contained in:
+1
-1
@@ -1064,7 +1064,7 @@ public class ControlFlowAnalyzer extends JavaElementVisitor {
|
||||
if (componentType != null) {
|
||||
generateBoxingUnboxingInstructionFor(initializer, componentType);
|
||||
if (componentNullability == Nullness.NOT_NULL) {
|
||||
addInstruction(new CheckNotNullInstruction(initializer, NullabilityProblem.assigningToNotNull));
|
||||
addInstruction(new CheckNotNullInstruction(initializer, NullabilityProblem.storingToNotNullArray));
|
||||
}
|
||||
}
|
||||
addInstruction(new PopInstruction());
|
||||
|
||||
+18
-3
@@ -325,7 +325,7 @@ public class DataFlowInspectionBase extends BaseJavaBatchLocalInspectionTool {
|
||||
|
||||
reportNullableFunctions(visitor, holder, reportedAnchors);
|
||||
reportNullableArguments(visitor, holder, reportedAnchors);
|
||||
reportNullableAssignments(visitor, holder, reportedAnchors);
|
||||
reportNullableAssignments(visitor, holder, reportedAnchors, onTheFly);
|
||||
reportUnboxedNullables(visitor, holder, reportedAnchors);
|
||||
reportNullableReturns(visitor, holder, reportedAnchors, scope);
|
||||
if (SUGGEST_NULLABLE_ANNOTATIONS) {
|
||||
@@ -682,14 +682,29 @@ public class DataFlowInspectionBase extends BaseJavaBatchLocalInspectionTool {
|
||||
}
|
||||
}
|
||||
|
||||
private static void reportNullableAssignments(DataFlowInstructionVisitor visitor, ProblemsHolder holder, Set<PsiElement> reportedAnchors) {
|
||||
private void reportNullableAssignments(DataFlowInstructionVisitor visitor,
|
||||
ProblemsHolder holder,
|
||||
Set<PsiElement> reportedAnchors,
|
||||
boolean onTheFly) {
|
||||
for (PsiElement expr : visitor.getProblems(NullabilityProblem.assigningToNotNull)) {
|
||||
if (!reportedAnchors.add(expr)) continue;
|
||||
assert expr instanceof PsiExpression;
|
||||
|
||||
final String text = isNullLiteralExpression(expr)
|
||||
? InspectionsBundle.message("dataflow.message.assigning.null")
|
||||
: InspectionsBundle.message("dataflow.message.assigning.nullable");
|
||||
holder.registerProblem(expr, text);
|
||||
holder.registerProblem(expr, text,
|
||||
createNPEFixes((PsiExpression)expr, (PsiExpression)expr, onTheFly).toArray(LocalQuickFix.EMPTY_ARRAY));
|
||||
}
|
||||
for (PsiElement expr : visitor.getProblems(NullabilityProblem.storingToNotNullArray)) {
|
||||
if (!reportedAnchors.add(expr)) continue;
|
||||
assert expr instanceof PsiExpression;
|
||||
|
||||
final String text = isNullLiteralExpression(expr)
|
||||
? InspectionsBundle.message("dataflow.message.storing.array.null")
|
||||
: InspectionsBundle.message("dataflow.message.storing.array.nullable");
|
||||
holder.registerProblem(expr, text,
|
||||
createNPEFixes((PsiExpression)expr, (PsiExpression)expr, onTheFly).toArray(LocalQuickFix.EMPTY_ARRAY));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
@@ -8,6 +8,7 @@ public enum NullabilityProblem {
|
||||
fieldAccessNPE,
|
||||
unboxingNullable,
|
||||
assigningToNotNull,
|
||||
storingToNotNullArray,
|
||||
nullableReturn,
|
||||
nullableFunctionReturn,
|
||||
passingNullableToNotNullParameter,
|
||||
|
||||
+5
-2
@@ -72,13 +72,16 @@ public class StandardInstructionVisitor extends InstructionVisitor {
|
||||
dfaDest = instruction.getAssignedValue();
|
||||
}
|
||||
|
||||
NullabilityProblem problem = PsiUtil.skipParenthesizedExprDown(instruction.getLExpression()) instanceof PsiArrayAccessExpression ?
|
||||
NullabilityProblem.storingToNotNullArray : NullabilityProblem.assigningToNotNull;
|
||||
|
||||
if (dfaDest instanceof DfaVariableValue) {
|
||||
DfaVariableValue var = (DfaVariableValue) dfaDest;
|
||||
|
||||
final PsiModifierListOwner psi = var.getPsiVariable();
|
||||
boolean forceDeclaredNullity = !(psi instanceof PsiParameter && psi.getParent() instanceof PsiParameterList);
|
||||
if (forceDeclaredNullity && var.getInherentNullability() == Nullness.NOT_NULL) {
|
||||
checkNotNullable(memState, dfaSource, NullabilityProblem.assigningToNotNull, instruction.getRExpression());
|
||||
checkNotNullable(memState, dfaSource, problem, instruction.getRExpression());
|
||||
}
|
||||
if (!(psi instanceof PsiField) || !psi.hasModifierProperty(PsiModifier.VOLATILE)) {
|
||||
memState.setVarValue(var, dfaSource);
|
||||
@@ -89,7 +92,7 @@ public class StandardInstructionVisitor extends InstructionVisitor {
|
||||
}
|
||||
|
||||
} else if (dfaDest instanceof DfaTypeValue && ((DfaTypeValue)dfaDest).isNotNull()) {
|
||||
checkNotNullable(memState, dfaSource, NullabilityProblem.assigningToNotNull, instruction.getRExpression());
|
||||
checkNotNullable(memState, dfaSource, problem, instruction.getRExpression());
|
||||
}
|
||||
|
||||
memState.push(dfaDest);
|
||||
|
||||
+10
@@ -21,6 +21,7 @@ import com.intellij.codeInspection.dataFlow.DfaInstructionState;
|
||||
import com.intellij.codeInspection.dataFlow.DfaMemoryState;
|
||||
import com.intellij.codeInspection.dataFlow.InstructionVisitor;
|
||||
import com.intellij.codeInspection.dataFlow.value.DfaValue;
|
||||
import com.intellij.psi.PsiAssignmentExpression;
|
||||
import com.intellij.psi.PsiExpression;
|
||||
import com.intellij.psi.PsiVariable;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -44,6 +45,15 @@ public class AssignInstruction extends Instruction {
|
||||
return myRExpression;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public PsiExpression getLExpression() {
|
||||
if(myRExpression == null) return null;
|
||||
if(myRExpression.getParent() instanceof PsiAssignmentExpression) {
|
||||
return ((PsiAssignmentExpression)myRExpression.getParent()).getLExpression();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean isVariableInitializer() {
|
||||
return myRExpression != null && myRExpression.getParent() instanceof PsiVariable;
|
||||
}
|
||||
|
||||
+11
-4
@@ -19,10 +19,17 @@ class FooImpl implements Foo {
|
||||
return null;
|
||||
}
|
||||
else if (Math.random() > 0.5) {
|
||||
@NotNull Object @Nullable [] arr1 = new Object[]{<warning descr="'null' is assigned to a variable that is annotated with @NotNull">null</warning>, new Object(), <warning descr="Expression 'Math.random() > 0.5 ? new Object() : null' might evaluate to null but is assigned to a variable that is annotated with @NotNull">Math.random() > 0.5 ? new Object() : null</warning>};
|
||||
@NotNull Object @Nullable [] arr2 = {<warning descr="'null' is assigned to a variable that is annotated with @NotNull">null</warning>, new Object(), <warning descr="Expression 'Math.random() > 0.5 ? new Object() : null' might evaluate to null but is assigned to a variable that is annotated with @NotNull">Math.random() > 0.5 ? new Object() : null</warning>};
|
||||
return new Object[]{<warning descr="'null' is assigned to a variable that is annotated with @NotNull">null</warning>, new Object(), <warning descr="Expression 'Math.random() > 0.5 ? new Object() : null' might evaluate to null but is assigned to a variable that is annotated with @NotNull">Math.random() > 0.5 ? new Object() : null</warning>};
|
||||
@NotNull Object @Nullable [] arr1 = new Object[]{<warning descr="'null' is stored to an array which elements are @NotNull">null</warning>, new Object(), <warning descr="Expression 'Math.random() > 0.5 ? new Object() : null' might evaluate to null but is stored to an array of @NotNull elements">Math.random() > 0.5 ? new Object() : null</warning>};
|
||||
@NotNull Object @Nullable [] arr2 = {<warning descr="'null' is stored to an array which elements are @NotNull">null</warning>, new Object(), <warning descr="Expression 'Math.random() > 0.5 ? new Object() : null' might evaluate to null but is stored to an array of @NotNull elements">Math.random() > 0.5 ? new Object() : null</warning>};
|
||||
return new Object[]{<warning descr="'null' is stored to an array which elements are @NotNull">null</warning>, new Object(), <warning descr="Expression 'Math.random() > 0.5 ? new Object() : null' might evaluate to null but is stored to an array of @NotNull elements">Math.random() > 0.5 ? new Object() : null</warning>};
|
||||
}
|
||||
return new @NotNull Object @Nullable []{<warning descr="'null' is assigned to a variable that is annotated with @NotNull">null</warning>, new Object(), <warning descr="Expression 'Math.random() > 0.5 ? new Object() : null' might evaluate to null but is assigned to a variable that is annotated with @NotNull">Math.random() > 0.5 ? new Object() : null</warning>};
|
||||
return new @NotNull Object @Nullable []{<warning descr="'null' is stored to an array which elements are @NotNull">null</warning>, new Object(), <warning descr="Expression 'Math.random() > 0.5 ? new Object() : null' might evaluate to null but is stored to an array of @NotNull elements">Math.random() > 0.5 ? new Object() : null</warning>};
|
||||
}
|
||||
|
||||
void test() {
|
||||
@NotNull Object @Nullable [] array = getNullableArrayOfNotNullObjects();
|
||||
assert array != null;
|
||||
array[0] = <warning descr="'null' is stored to an array which elements are @NotNull">null</warning>;
|
||||
array[1] = <warning descr="Expression 'Math.random() > 0.5 ? null : \"foo\"' might evaluate to null but is stored to an array of @NotNull elements">Math.random() > 0.5 ? null : "foo"</warning>;
|
||||
}
|
||||
}
|
||||
@@ -85,6 +85,8 @@ dataflow.message.passing.nullable.argument=Argument <code>#ref</code> #loc might
|
||||
dataflow.message.passing.nullable.argument.methodref=Method reference argument might be null
|
||||
dataflow.message.assigning.null=<code>null</code> is assigned to a variable that is annotated with @NotNull
|
||||
dataflow.message.assigning.nullable=Expression <code>#ref</code> might evaluate to null but is assigned to a variable that is annotated with @NotNull
|
||||
dataflow.message.storing.array.null=<code>null</code> is stored to an array which elements are @NotNull
|
||||
dataflow.message.storing.array.nullable=Expression <code>#ref</code> might evaluate to null but is stored to an array of @NotNull elements
|
||||
dataflow.message.return.null.from.notnull=<code>null</code> is returned by the method declared as @{0}
|
||||
dataflow.message.return.nullable.from.notnull=Expression <code>#ref</code> might evaluate to null but is returned by the method declared as @{0}
|
||||
dataflow.message.return.null.from.notnullable=<code>null</code> is returned by the method which is not declared as @{0}
|
||||
|
||||
Reference in New Issue
Block a user