From 008d3a6e495d6c2585ee7f6cc13900bce07cfb58 Mon Sep 17 00:00:00 2001 From: Tagir Valeev Date: Mon, 24 Dec 2018 15:45:53 +0700 Subject: [PATCH] IDEA-204641 Exception throwing analysis doesn't account for runtime exceptions in functions --- .../codeInspection/dataFlow/CFGBuilder.java | 5 ++++- .../dataFlow/ControlFlowAnalyzer.java | 14 +++++--------- .../dataFlow/fixture/MapUpdateInlining.java | 19 +++++++++++++++++++ 3 files changed, 28 insertions(+), 10 deletions(-) diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/CFGBuilder.java b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/CFGBuilder.java index 5ec94c79c200..bd27ca4d1c61 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/CFGBuilder.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/CFGBuilder.java @@ -690,7 +690,10 @@ public class CFGBuilder { } // Unknown function flushFields(); - PsiType returnType = LambdaUtil.getFunctionalInterfaceReturnType(functionalExpression.getType()); + myAnalyzer.addConditionalRuntimeThrow(); + PsiType functionalInterfaceType = functionalExpression.getType(); + myAnalyzer.addMethodThrows(LambdaUtil.getFunctionalInterfaceMethod(functionalInterfaceType), null); + PsiType returnType = LambdaUtil.getFunctionalInterfaceReturnType(functionalInterfaceType); if (returnType != null) { push(getFactory().createTypeValue(returnType, DfaPsiUtil.getTypeNullability(returnType))); } 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 3b5775eeb66f..24c65a6cb1a1 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 @@ -1041,7 +1041,7 @@ public class ControlFlowAnalyzer extends JavaElementVisitor { finishElement(statement); } - private void addConditionalRuntimeThrow() { + void addConditionalRuntimeThrow() { if (!shouldHandleException()) { return; } @@ -1655,8 +1655,8 @@ public class ControlFlowAnalyzer extends JavaElementVisitor { finishElement(expression); } - private void addMethodThrows(PsiMethod method, @Nullable PsiElement explicitCall) { - if (method != null) { + void addMethodThrows(PsiMethod method, @Nullable PsiElement explicitCall) { + if (method != null && shouldHandleException()) { addThrows(explicitCall, method.getThrowsList().getReferencedTypes()); } } @@ -1774,9 +1774,7 @@ public class ControlFlowAnalyzer extends JavaElementVisitor { ifNotFail.setOffset(myCurrentFlow.getInstructionCount()); } - if (shouldHandleException()) { - addMethodThrows(method, anchor); - } + addMethodThrows(method, anchor); } /** @@ -1862,9 +1860,7 @@ public class ControlFlowAnalyzer extends JavaElementVisitor { List contracts = constructor == null ? Collections.emptyList() : JavaMethodContractUtil.getMethodContracts(constructor); addInstruction(new MethodCallInstruction(expression, precalculatedNewValue, contracts)); - if (shouldHandleException()) { - addMethodThrows(constructor, expression); - } + addMethodThrows(constructor, expression); } finishElement(expression); diff --git a/java/java-tests/testData/inspection/dataFlow/fixture/MapUpdateInlining.java b/java/java-tests/testData/inspection/dataFlow/fixture/MapUpdateInlining.java index d1486277bb3e..66f062b18602 100644 --- a/java/java-tests/testData/inspection/dataFlow/fixture/MapUpdateInlining.java +++ b/java/java-tests/testData/inspection/dataFlow/fixture/MapUpdateInlining.java @@ -2,6 +2,7 @@ import foo.*; import java.util.Map; import java.util.HashMap; +import java.util.function.Function; class MapUpdateInlining { void testKey(Map map) { @@ -82,4 +83,22 @@ class MapUpdateInlining { } native void doSmth(); + + // IDEA-204641 + public static void testAnyLambda(@NotNull Function lambda) { + Map map = new HashMap<>(); + Throwable thrown = null; + try { + map.computeIfAbsent("a", lambda); + } + catch (Throwable t) { + thrown = t; + throw t; + } + finally { + if (thrown != null) { // possible + int x = 0; + } + } + } }