From 9a837e70d3a98dc6883590167fbb1ef0a60b2b5a Mon Sep 17 00:00:00 2001 From: Tagir Valeev Date: Wed, 10 Jan 2018 15:05:55 +0700 Subject: [PATCH] DFA: remove CAN_BE_NULL fact in removeEquivalenceRelations to allow merging null and not-null vars Fixes IDEA-184723 Data flow algorithm complexity --- .../dataFlow/DfaMemoryStateImpl.java | 7 +++ .../dataFlow/fixture/OptionalTooComplex.java | 48 +++++++++++++++++++ .../DataFlowInspection8Test.java | 2 + 3 files changed, 57 insertions(+) create mode 100644 java/java-tests/testData/inspection/dataFlow/fixture/OptionalTooComplex.java diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DfaMemoryStateImpl.java b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DfaMemoryStateImpl.java index c70bf120bc66..47cc4115b7ac 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DfaMemoryStateImpl.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DfaMemoryStateImpl.java @@ -1298,6 +1298,13 @@ public class DfaMemoryStateImpl implements DfaMemoryState { final int idPlain = varPlain.getID(); final int idNegated = varNegated == null ? -1 : varNegated.getID(); + if(isNull(varPlain) || isNotNull(varPlain)) { + DfaVariableState state = myVariableStates.get(varPlain); + if (state != null) { + setVariableState(varPlain, state.withoutFact(DfaFactType.CAN_BE_NULL)); + } + } + int[] classes = myIdToEqClassesIndices.get(idPlain); int[] negatedClasses = myIdToEqClassesIndices.get(idNegated); int[] result = ArrayUtil diff --git a/java/java-tests/testData/inspection/dataFlow/fixture/OptionalTooComplex.java b/java/java-tests/testData/inspection/dataFlow/fixture/OptionalTooComplex.java new file mode 100644 index 000000000000..0beb16c50f15 --- /dev/null +++ b/java/java-tests/testData/inspection/dataFlow/fixture/OptionalTooComplex.java @@ -0,0 +1,48 @@ +import java.util.Optional; + +// IDEA-184723 +class OptionalTooComplex { + // Should not be too complex + public Long fetch() { + final PreparedStatement ps = builder + .setInteger(opt().orElse(null)) + .setInteger(opt().orElse(null)) + .setInteger(opt().orElse(null)) + .setInteger(opt().orElse(null)) + .setInteger(opt().orElse(null)) + .build(); + + ResultSet rs = null; + try { + rs = ps.executeQuery(); + if (rs.next()) { + return rs.getLong(); + } + } catch (final Exception e) { + throw new RuntimeException(e); + } finally { + } + + return 0L; + } + + interface ResultSet { + boolean next() throws Exception; + + long getLong() throws Exception; + } + + interface PreparedStatement { + ResultSet executeQuery() throws Exception; + } + + native Optional opt(); + + interface QueryBuilder { + QueryBuilder setInteger(Integer value); + + PreparedStatement build(); + } + + QueryBuilder builder; +} diff --git a/java/java-tests/testSrc/com/intellij/java/codeInspection/DataFlowInspection8Test.java b/java/java-tests/testSrc/com/intellij/java/codeInspection/DataFlowInspection8Test.java index 94bdd47b19e8..6777aa2d2c29 100644 --- a/java/java-tests/testSrc/com/intellij/java/codeInspection/DataFlowInspection8Test.java +++ b/java/java-tests/testSrc/com/intellij/java/codeInspection/DataFlowInspection8Test.java @@ -220,4 +220,6 @@ public class DataFlowInspection8Test extends DataFlowInspectionTestCase { public void testPrimitiveGetters() { doTest(); } public void testUnknownOnStack() { doTest(); } public void testMapUpdateInlining() { doTestWithCustomAnnotations(); } + + public void testOptionalTooComplex() { doTest(); } } \ No newline at end of file