From 4c551c12c78e7c59793891815e9778e3bbb5d7fe Mon Sep 17 00:00:00 2001 From: Bas Leijdekkers Date: Thu, 2 Sep 2010 17:33:29 +0200 Subject: [PATCH] IDEA-58106 ("Infinite recursion" inspection breaks with tautological if's) --- .../ig/bugs/InfiniteRecursionInspection.java | 6 +- .../com/siyeh/ig/psiutils/RecursionUtils.java | 33 ++++++---- .../InfiniteRecursion.java} | 24 +++++++- .../bugs/infinite_recursion/expected.xml | 60 +++++++++++++++++++ .../bugs/InfiniteRecursionInspectionTest.java | 26 ++++++++ 5 files changed, 132 insertions(+), 17 deletions(-) rename plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/{InfiniteRecursionInspection.java => infinite_recursion/InfiniteRecursion.java} (83%) create mode 100644 plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/infinite_recursion/expected.xml create mode 100644 plugins/InspectionGadgets/testsrc/com/siyeh/ig/bugs/InfiniteRecursionInspectionTest.java diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/bugs/InfiniteRecursionInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/bugs/InfiniteRecursionInspection.java index 517d605fd84a..3573a3b90961 100644 --- a/plugins/InspectionGadgets/src/com/siyeh/ig/bugs/InfiniteRecursionInspection.java +++ b/plugins/InspectionGadgets/src/com/siyeh/ig/bugs/InfiniteRecursionInspection.java @@ -1,5 +1,5 @@ /* - * Copyright 2003-2007 Dave Griffith, Bas Leijdekkers + * Copyright 2003-2010 Dave Griffith, Bas Leijdekkers * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -25,22 +25,26 @@ import org.jetbrains.annotations.NotNull; public class InfiniteRecursionInspection extends BaseInspection { + @Override @NotNull public String getDisplayName() { return InspectionGadgetsBundle.message( "infinite.recursion.display.name"); } + @Override @NotNull public String buildErrorString(Object... infos) { return InspectionGadgetsBundle.message( "infinite.recursion.problem.descriptor"); } + @Override public boolean isEnabledByDefault(){ return true; } + @Override public BaseInspectionVisitor buildVisitor() { return new InfiniteRecursionVisitor(); } diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/psiutils/RecursionUtils.java b/plugins/InspectionGadgets/src/com/siyeh/ig/psiutils/RecursionUtils.java index 702ade418dee..c55212e1bfdd 100644 --- a/plugins/InspectionGadgets/src/com/siyeh/ig/psiutils/RecursionUtils.java +++ b/plugins/InspectionGadgets/src/com/siyeh/ig/psiutils/RecursionUtils.java @@ -1,5 +1,5 @@ /* - * Copyright 2003-2006 Dave Griffith, Bas Leijdekkers + * Copyright 2003-2010 Dave Griffith, Bas Leijdekkers * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -353,13 +353,10 @@ public class RecursionUtils{ private static boolean referenceExpressionDefinitelyRecurses( PsiReferenceExpression expression, PsiMethod method){ - final PsiExpression qualifierExpression = expression.getQualifierExpression(); - if(qualifierExpression != null){ - return expressionDefinitelyRecurses(qualifierExpression, method); - } - return false; + return qualifierExpression != null && + expressionDefinitelyRecurses(qualifierExpression, method); } private static boolean typeCastExpressionDefinitelyRecurses( @@ -573,9 +570,17 @@ public class RecursionUtils{ } final PsiStatement thenBranch = ifStatement.getThenBranch(); final PsiStatement elseBranch = ifStatement.getElseBranch(); - if(thenBranch == null || elseBranch == null){ + if(thenBranch == null){ return false; } + final Object value = + ExpressionUtils.computeConstantExpression(condition); + if (value == Boolean.TRUE) { + return statementDefinitelyRecurses(thenBranch, method); + } else if (value == Boolean.FALSE) { + return elseBranch != null && + statementDefinitelyRecurses(elseBranch, method); + } return statementDefinitelyRecurses(thenBranch, method) && statementDefinitelyRecurses(elseBranch, method); } @@ -590,7 +595,9 @@ public class RecursionUtils{ if(expressionDefinitelyRecurses(condition, method)){ return true; } - if(BoolUtils.isTrue(condition)){ + final Object value = + ExpressionUtils.computeConstantExpression(condition); + if(value == Boolean.TRUE) { final PsiStatement body = forStatement.getBody(); return statementDefinitelyRecurses(body, method); } @@ -610,7 +617,9 @@ public class RecursionUtils{ if(expressionDefinitelyRecurses(condition, method)){ return true; } - if(BoolUtils.isTrue(condition)){ + final Object value = + ExpressionUtils.computeConstantExpression(condition); + if(value == Boolean.TRUE){ final PsiStatement body = whileStatement.getBody(); return statementDefinitelyRecurses(body, method); } @@ -637,9 +646,7 @@ public class RecursionUtils{ public static boolean methodDefinitelyRecurses( @NotNull PsiMethod method){ final PsiCodeBlock body = method.getBody(); - if(body == null){ - return false; - } - return !codeBlockMayReturnBeforeRecursing(body, method, true); + return body != null && + !codeBlockMayReturnBeforeRecursing(body, method, true); } } diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/InfiniteRecursionInspection.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/infinite_recursion/InfiniteRecursion.java similarity index 83% rename from plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/InfiniteRecursionInspection.java rename to plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/infinite_recursion/InfiniteRecursion.java index ea1d44959866..7a04c43427b4 100644 --- a/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/InfiniteRecursionInspection.java +++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/infinite_recursion/InfiniteRecursion.java @@ -1,4 +1,4 @@ -package com.siyeh.igtest.bugs; +package com.siyeh.igtest.bugs.infinite_recursion; import com.intellij.psi.PsiClass; @@ -6,11 +6,11 @@ import java.util.List; import java.io.IOException; import java.io.File; -public class InfiniteRecursionInspection +public class InfiniteRecursion { public void foo() { - new InfiniteRecursionInspection().foo(); + new InfiniteRecursion().foo(); } public void bar() @@ -122,4 +122,22 @@ public class InfiniteRecursionInspection rec(pc); } } + + void foo1() { + for (;true && true || false;) { + foo1(); + } + } + + void foo2() { + if (true || false) { + foo2(); + } + } + + void bar1() { + while (true || false) { + bar1(); + } + } } diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/infinite_recursion/expected.xml b/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/infinite_recursion/expected.xml new file mode 100644 index 000000000000..9f9c5dd54de5 --- /dev/null +++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/infinite_recursion/expected.xml @@ -0,0 +1,60 @@ + + + + InfiniteRecursion.java + 21 + Infinite recursion + Method <code>baz()</code> recurses infinitely, and can only end by throwing an exception #loc + + + + InfiniteRecursion.java + 52 + Infinite recursion + Method <code>barangoo()</code> recurses infinitely, and can only end by throwing an exception #loc + + + + + InfiniteRecursion.java + 61 + Infinite recursion + Method <code>bazoomer()</code> recurses infinitely, and can only end by throwing an exception #loc + + + + + InfiniteRecursion.java + 78 + Infinite recursion + Method <code>foobarangus()</code> recurses infinitely, and can only end by throwing an exception #loc + + + + + + InfiniteRecursion.java + 126 + Infinite recursion + Method <code>foo1()</code> recurses infinitely, and can only end by throwing an exception #loc + + + + InfiniteRecursion.java + 132 + Infinite recursion + Method <code>foo2()</code> recurses infinitely, and can only end by throwing an exception #loc + + + + + + + InfiniteRecursion.java + 138 + Infinite recursion + Method <code>bar1()</code> recurses infinitely, and can only end by throwing an exception #loc + + + + \ No newline at end of file diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/bugs/InfiniteRecursionInspectionTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/bugs/InfiniteRecursionInspectionTest.java new file mode 100644 index 000000000000..a1d5234e3e0d --- /dev/null +++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/bugs/InfiniteRecursionInspectionTest.java @@ -0,0 +1,26 @@ +/* + * Copyright 2000-2010 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.siyeh.ig.bugs; + +import com.IGInspectionTestCase; + +public class InfiniteRecursionInspectionTest extends IGInspectionTestCase { + + public void test() throws Exception { + doTest("com/siyeh/igtest/bugs/infinite_recursion", + new InfiniteRecursionInspection()); + } +} \ No newline at end of file