diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/bytecodeAnalysis/Parameters.java b/java/java-analysis-impl/src/com/intellij/codeInspection/bytecodeAnalysis/Parameters.java index 28188fc42786..24d2f4b9c963 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/bytecodeAnalysis/Parameters.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/bytecodeAnalysis/Parameters.java @@ -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 { break; default: nextFrame = new Frame(frame); - interpreter.reset(); + interpreter.reset(false); nextFrame.execute(insnNode, interpreter); subResult = interpreter.getSubResult(); } @@ -501,7 +500,7 @@ class NullableInAnalysis extends Analysis { List 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 { pending[pendingTop++] = state; } - private void execute(Frame frame, AbstractInsnNode insnNode) throws AnalyzerException { + private void execute(Frame frame, AbstractInsnNode insnNode, boolean taken) throws AnalyzerException { switch (insnNode.getType()) { case AbstractInsnNode.LABEL: case AbstractInsnNode.LINE: @@ -592,7 +591,7 @@ class NullableInAnalysis extends Analysis { break; default: nextFrame = new Frame(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 && "".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);