diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/ControlFlowAnalyzer.java b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/ControlFlowAnalyzer.java index fb5247851825..20300e6cc281 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/ControlFlowAnalyzer.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/ControlFlowAnalyzer.java @@ -51,6 +51,7 @@ class ControlFlowAnalyzer extends JavaElementVisitor { private Stack myCatchStack; private DfaValue myRuntimeException; private DfaValue myError; + private PsiType myNpe; ControlFlowAnalyzer(final DfaValueFactory valueFactory) { myFactory = valueFactory; @@ -62,6 +63,7 @@ class ControlFlowAnalyzer extends JavaElementVisitor { GlobalSearchScope scope = codeFragment.getResolveScope(); myRuntimeException = myFactory.getNotNullFactory().create(PsiType.getJavaLangRuntimeException(manager, scope)); myError = myFactory.getNotNullFactory().create(PsiType.getJavaLangError(manager, scope)); + myNpe = JavaPsiFacade.getElementFactory(manager.getProject()).createTypeByFQClassName(JAVA_LANG_NULL_POINTER_EXCEPTION, scope); myFields = new HashSet(); myCatchStack = new Stack(); myPassNumber = 1; @@ -642,6 +644,13 @@ class ControlFlowAnalyzer extends JavaElementVisitor { if (exception != null) { exception.accept(this); + addInstruction(new DupInstruction()); + addInstruction(new PushInstruction(myFactory.getConstFactory().getNull(), null)); + addInstruction(new BinopInstruction(JavaTokenType.EQEQ, null, statement.getProject())); + ConditionalGotoInstruction gotoInstruction = new ConditionalGotoInstruction(-1, true, null); + addInstruction(gotoInstruction); + addThrowCode(myNpe); + gotoInstruction.setOffset(myCurrentFlow.getInstructionCount()); addThrowCode(exception.getType()); } @@ -1019,7 +1028,7 @@ class ControlFlowAnalyzer extends JavaElementVisitor { @Nullable private static IElementType substituteBinaryOperation(IElementType op, PsiType type) { - if (JavaTokenType.PLUS == op && (type == null || !type.equalsToText(CommonClassNames.JAVA_LANG_STRING))) { + if (JavaTokenType.PLUS == op && (type == null || !type.equalsToText(JAVA_LANG_STRING))) { return null; } return op; @@ -1266,7 +1275,7 @@ class ControlFlowAnalyzer extends JavaElementVisitor { if (expressions.length == 1 && method instanceof PsiMethod && "equals".equals(((PsiMethod)method).getName()) && parameters.length == 1 && - parameters[0].getType().equalsToText(CommonClassNames.JAVA_LANG_OBJECT) && + parameters[0].getType().equalsToText(JAVA_LANG_OBJECT) && PsiType.BOOLEAN.equals(((PsiMethod)method).getReturnType())) { addInstruction(new PushInstruction(myFactory.getConstFactory().getFalse(), null)); addInstruction(new SwapInstruction()); @@ -1438,7 +1447,7 @@ class ControlFlowAnalyzer extends JavaElementVisitor { addInstruction(new PopInstruction()); } } - addInstruction(new MethodCallInstruction(expression, (DfaValue)null)); + addInstruction(new MethodCallInstruction(expression, null)); } else { final PsiExpressionList args = expression.getArgumentList(); @@ -1455,7 +1464,7 @@ class ControlFlowAnalyzer extends JavaElementVisitor { } } - addInstruction(new MethodCallInstruction(expression, (DfaValue)null)); + addInstruction(new MethodCallInstruction(expression, null)); if (!myCatchStack.isEmpty()) { addMethodThrows(ctr); diff --git a/java/java-tests/testData/inspection/dataFlow/fixture/ThrowNull.java b/java/java-tests/testData/inspection/dataFlow/fixture/ThrowNull.java new file mode 100644 index 000000000000..e35aa2f0dcd0 --- /dev/null +++ b/java/java-tests/testData/inspection/dataFlow/fixture/ThrowNull.java @@ -0,0 +1,13 @@ +public class DataFlowBug { + + public void add2() { + try { + throw null; + } catch (Throwable e) { + if (e instanceof NullPointerException) { + return; + } + } + } + +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/codeInspection/DataFlowInspectionTest.java b/java/java-tests/testSrc/com/intellij/codeInspection/DataFlowInspectionTest.java index 2b5f96a48f59..83d7dafa3df1 100644 --- a/java/java-tests/testSrc/com/intellij/codeInspection/DataFlowInspectionTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInspection/DataFlowInspectionTest.java @@ -169,6 +169,7 @@ public class DataFlowInspectionTest extends LightCodeInsightFixtureTestCase { public void testTransientFinalField() { doTest(); } public void _testSymmetricUncheckedCast() { doTest(); } public void testNullCheckDoesntAffectUncheckedCast() { doTest(); } + public void testThrowNull() { doTest(); } public void testNullableForeachVariable() { setupCustomAnnotations(); diff --git a/platform/core-api/src/com/intellij/psi/CommonClassNames.java b/platform/core-api/src/com/intellij/psi/CommonClassNames.java index 1534e82106e2..6d8d16172cb4 100644 --- a/platform/core-api/src/com/intellij/psi/CommonClassNames.java +++ b/platform/core-api/src/com/intellij/psi/CommonClassNames.java @@ -91,6 +91,8 @@ public interface CommonClassNames { @NonNls String JAVA_LANG_CLONEABLE = "java.lang.Cloneable"; @NonNls String JAVA_LANG_COMPARABLE = "java.lang.Comparable"; + @NonNls String JAVA_LANG_NULL_POINTER_EXCEPTION = "java.lang.NullPointerException"; + @NonNls String JAVA_UTIL_CONCURRENT_FUTURE = "java.util.concurrent.Future"; @NonNls String JAVA_UTIL_CONCURRENT_CALLABLE = "java.util.concurrent.Callable";