IDEA-145968: fixed @Nullable inference

This commit is contained in:
Ilya Klyuchnikov
2015-10-12 15:00:21 +03:00
parent 7b18b38c05
commit 4fc4a5561c
@@ -33,8 +33,7 @@ import java.util.HashSet;
import java.util.List;
import java.util.Set;
import static com.intellij.codeInspection.bytecodeAnalysis.AbstractValues.InstanceOfCheckValue;
import static com.intellij.codeInspection.bytecodeAnalysis.AbstractValues.ParamValue;
import static com.intellij.codeInspection.bytecodeAnalysis.AbstractValues.*;
import static com.intellij.codeInspection.bytecodeAnalysis.PResults.*;
import static org.jetbrains.org.objectweb.asm.Opcodes.*;
import static com.intellij.codeInspection.bytecodeAnalysis.Direction.*;
@@ -401,7 +400,7 @@ class NonNullInAnalysis extends Analysis<PResult> {
break;
default:
nextFrame = new Frame<BasicValue>(frame);
interpreter.reset();
interpreter.reset(false);
nextFrame.execute(insnNode, interpreter);
subResult = interpreter.getSubResult();
}
@@ -501,7 +500,7 @@ class NullableInAnalysis extends Analysis<PResult> {
List<Conf> nextHistory = dfsTree.loopEnters[insnIndex] ? append(history, conf) : history;
addComputed(insnIndex, state);
execute(frame, insnNode);
execute(frame, insnNode, taken);
if (subResult == NPE || top) {
earlyResult = NPE;
@@ -581,7 +580,7 @@ class NullableInAnalysis extends Analysis<PResult> {
pending[pendingTop++] = state;
}
private void execute(Frame<BasicValue> frame, AbstractInsnNode insnNode) throws AnalyzerException {
private void execute(Frame<BasicValue> frame, AbstractInsnNode insnNode, boolean taken) throws AnalyzerException {
switch (insnNode.getType()) {
case AbstractInsnNode.LABEL:
case AbstractInsnNode.LINE:
@@ -592,7 +591,7 @@ class NullableInAnalysis extends Analysis<PResult> {
break;
default:
nextFrame = new Frame<BasicValue>(frame);
interpreter.reset();
interpreter.reset(taken);
nextFrame.execute(insnNode, interpreter);
subResult = interpreter.getSubResult();
top = interpreter.top;
@@ -605,6 +604,7 @@ abstract class NullityInterpreter extends BasicInterpreter {
final boolean nullableAnalysis;
final int nullityMask;
private PResult subResult = Identity;
protected boolean taken;
NullityInterpreter(boolean nullableAnalysis, int nullityMask) {
this.nullableAnalysis = nullableAnalysis;
@@ -616,9 +616,10 @@ abstract class NullityInterpreter extends BasicInterpreter {
public PResult getSubResult() {
return subResult;
}
void reset() {
void reset(boolean taken) {
subResult = Identity;
top = false;
this.taken = taken;
}
@Override
@@ -728,7 +729,8 @@ abstract class NullityInterpreter extends BasicInterpreter {
MethodInsnNode methodNode = (MethodInsnNode) insn;
Method method = new Method(methodNode.owner, methodNode.name, methodNode.desc);
for (int i = shift; i < values.size(); i++) {
if (values.get(i) instanceof ParamValue) {
BasicValue value = values.get(i);
if (value instanceof ParamValue || (NullValue == value && nullityMask == In.NULLABLE_MASK && "<init>".equals(methodNode.name))) {
subResult = combine(subResult, new ConditionalNPE(new Key(method, new In(i - shift, nullityMask), stable)));
}
}
@@ -757,6 +759,14 @@ class NullableInterpreter extends NullityInterpreter {
super(true, In.NULLABLE_MASK);
}
@Override
public BasicValue newOperation(AbstractInsnNode insn) throws AnalyzerException {
if (insn.getOpcode() == ACONST_NULL && taken) {
return NullValue;
}
return super.newOperation(insn);
}
@Override
PResult combine(PResult res1, PResult res2) throws AnalyzerException {
return join(res1, res2);