diff --git a/java/java-impl/src/com/intellij/codeInspection/dataFlow/DataFlowRunner.java b/java/java-impl/src/com/intellij/codeInspection/dataFlow/DataFlowRunner.java index 9395f50f13c4..9efe5a3894b8 100644 --- a/java/java-impl/src/com/intellij/codeInspection/dataFlow/DataFlowRunner.java +++ b/java/java-impl/src/com/intellij/codeInspection/dataFlow/DataFlowRunner.java @@ -32,6 +32,7 @@ import com.intellij.codeInspection.dataFlow.value.DfaVariableValue; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.progress.ProgressManager; +import com.intellij.openapi.util.Key; import com.intellij.openapi.util.Pair; import com.intellij.psi.*; import gnu.trove.THashSet; @@ -42,7 +43,8 @@ import java.util.*; public class DataFlowRunner { private static final Logger LOG = Logger.getInstance("#com.intellij.codeInspection.dataFlow.DataFlowRunner"); - private static final long ourTimeLimit = 10000; + private static final Key TOO_EXPENSIVE_SIZE = Key.create("TOO_EXPENSIVE_SIZE"); + private static final long ourTimeLimit = 1000; private Instruction[] myInstructions; private DfaVariableValue[] myFields; @@ -107,13 +109,11 @@ public class DataFlowRunner { } } - int branchCount = 0; - for (Instruction instruction : myInstructions) { - if (instruction instanceof BranchingInstruction) branchCount++; + Integer tooExpensiveSize = psiBlock.getUserData(TOO_EXPENSIVE_SIZE); + if (tooExpensiveSize != null && tooExpensiveSize == psiBlock.getTextLength()) { + return RunnerResult.TOO_COMPLEX; } - if (branchCount > 80) return RunnerResult.TOO_COMPLEX; // Do not even try. Definitely will out of time. - final ArrayList queue = new ArrayList(); for (final DfaMemoryState initialState : initialStates) { queue.add(new DfaInstructionState(myInstructions[0], initialState)); @@ -124,7 +124,10 @@ public class DataFlowRunner { final long before = System.currentTimeMillis(); int count = 0; while (!queue.isEmpty()) { - if (count % 50 == 0 && !unitTestMode && System.currentTimeMillis() - before > timeLimit) return RunnerResult.TOO_COMPLEX; + if (count % 50 == 0 && !unitTestMode && System.currentTimeMillis() - before > timeLimit) { + psiBlock.putUserData(TOO_EXPENSIVE_SIZE, psiBlock.getTextLength()); + return RunnerResult.TOO_COMPLEX; + } ProgressManager.checkCanceled(); DfaInstructionState instructionState = queue.remove(0); @@ -155,6 +158,7 @@ public class DataFlowRunner { count++; } + psiBlock.putUserData(TOO_EXPENSIVE_SIZE, null); return RunnerResult.OK; } catch (ArrayIndexOutOfBoundsException e) { diff --git a/java/java-tests/testData/inspection/dataFlow/fixture/BigMethodNotComplex.java b/java/java-tests/testData/inspection/dataFlow/fixture/BigMethodNotComplex.java new file mode 100644 index 000000000000..8a1ff44e9ca2 --- /dev/null +++ b/java/java-tests/testData/inspection/dataFlow/fixture/BigMethodNotComplex.java @@ -0,0 +1,56 @@ +public abstract class DDD { + abstract boolean condition(); + abstract Object foo(); + abstract Object bar(); + + void test(Object o, DDD another) { + try { + System.out.println(condition() && equals(o) ? another.foo() : another.bar()); + System.out.println(condition() && equals(o) ? another.foo() : another.bar()); + System.out.println(condition() && equals(o) ? another.foo() : another.bar()); + System.out.println(condition() && equals(o) ? another.foo() : another.bar()); + System.out.println(condition() && equals(o) ? another.foo() : another.bar()); + System.out.println(condition() && equals(o) ? another.foo() : another.bar()); + System.out.println(condition() && equals(o) ? another.foo() : another.bar()); + System.out.println(condition() && equals(o) ? another.foo() : another.bar()); + System.out.println(condition() && equals(o) ? another.foo() : another.bar()); + System.out.println(condition() && equals(o) ? another.foo() : another.bar()); + System.out.println(condition() && equals(o) ? another.foo() : another.bar()); + System.out.println(condition() && equals(o) ? another.foo() : another.bar()); + System.out.println(condition() && equals(o) ? another.foo() : another.bar()); + System.out.println(condition() && equals(o) ? another.foo() : another.bar()); + System.out.println(condition() && equals(o) ? another.foo() : another.bar()); + System.out.println(condition() && equals(o) ? another.foo() : another.bar()); + System.out.println(condition() && equals(o) ? another.foo() : another.bar()); + System.out.println(condition() && equals(o) ? another.foo() : another.bar()); + System.out.println(condition() && equals(o) ? another.foo() : another.bar()); + System.out.println(condition() && equals(o) ? another.foo() : another.bar()); + System.out.println(condition() && equals(o) ? another.foo() : another.bar()); + System.out.println(condition() && equals(o) ? another.foo() : another.bar()); + System.out.println(condition() && equals(o) ? another.foo() : another.bar()); + System.out.println(condition() && equals(o) ? another.foo() : another.bar()); + System.out.println(condition() && equals(o) ? another.foo() : another.bar()); + System.out.println(condition() && equals(o) ? another.foo() : another.bar()); + System.out.println(condition() && equals(o) ? another.foo() : another.bar()); + System.out.println(condition() && equals(o) ? another.foo() : another.bar()); + System.out.println(condition() && equals(o) ? another.foo() : another.bar()); + System.out.println(condition() && equals(o) ? another.foo() : another.bar()); + System.out.println(condition() && equals(o) ? another.foo() : another.bar()); + System.out.println(condition() && equals(o) ? another.foo() : another.bar()); + System.out.println(condition() && equals(o) ? another.foo() : another.bar()); + System.out.println(condition() && equals(o) ? another.foo() : another.bar()); + System.out.println(condition() && equals(o) ? another.foo() : another.bar()); + System.out.println(condition() && equals(o) ? another.foo() : another.bar()); + System.out.println(condition() && equals(o) ? another.foo() : another.bar()); + System.out.println(condition() && equals(o) ? another.foo() : another.bar()); + System.out.println(condition() && equals(o) ? another.foo() : another.bar()); + System.out.println(condition() && equals(o) ? another.foo() : another.bar()); + System.out.println(condition() && equals(o) ? another.foo() : another.bar()); + System.out.println(condition() && equals(o) ? another.foo() : another.bar()); + } + catch (Exception e) { + System.out.println(e); + } + } + +} diff --git a/java/java-tests/testSrc/com/intellij/codeInspection/DataFlowInspectionFixtureTest.java b/java/java-tests/testSrc/com/intellij/codeInspection/DataFlowInspectionFixtureTest.java index 9b6bd4cf2ce7..da21b7b2739e 100644 --- a/java/java-tests/testSrc/com/intellij/codeInspection/DataFlowInspectionFixtureTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInspection/DataFlowInspectionFixtureTest.java @@ -1,3 +1,18 @@ +/* + * Copyright 2000-2012 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package com.intellij.codeInspection; import com.intellij.JavaTestUtil; @@ -23,7 +38,7 @@ public class DataFlowInspectionFixtureTest extends JavaCodeInsightFixtureTestCas final DataFlowInspection inspection = new DataFlowInspection(); inspection.SUGGEST_NULLABLE_ANNOTATIONS = true; myFixture.enableInspections(inspection); - myFixture.testHighlighting(true, false, false, getTestName(false) + ".java"); + myFixture.testHighlighting(true, false, true, getTestName(false) + ".java"); } public void testTryInAnonymous() throws Throwable { doTest(); } @@ -35,4 +50,6 @@ public class DataFlowInspectionFixtureTest extends JavaCodeInsightFixtureTestCas public void testFieldInAnonymous() throws Throwable { doTest(); } public void testNullableField() throws Throwable { doTest(); } public void testCanBeNullDoesntImplyIsNull() throws Throwable { doTest(); } + + public void testBigMethodNotComplex() throws Throwable { doTest(); } }