IDEA-58106 ("Infinite recursion" inspection breaks with tautological if's)

This commit is contained in:
Bas Leijdekkers
2010-09-02 17:33:29 +02:00
parent 665d888ac8
commit 4c551c12c7
5 changed files with 132 additions and 17 deletions
@@ -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();
}
@@ -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);
}
}
@@ -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();
}
}
}
@@ -0,0 +1,60 @@
<?xml version="1.0" encoding="UTF-8"?>
<problems>
<problem>
<file>InfiniteRecursion.java</file>
<line>21</line>
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Infinite recursion</problem_class>
<description>Method &lt;code&gt;baz()&lt;/code&gt; recurses infinitely, and can only end by throwing an exception #loc</description>
</problem>
<problem>
<file>InfiniteRecursion.java</file>
<line>52</line>
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Infinite recursion</problem_class>
<description>Method &lt;code&gt;barangoo()&lt;/code&gt; recurses infinitely, and can only end by throwing an exception #loc
</description>
</problem>
<problem>
<file>InfiniteRecursion.java</file>
<line>61</line>
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Infinite recursion</problem_class>
<description>Method &lt;code&gt;bazoomer()&lt;/code&gt; recurses infinitely, and can only end by throwing an exception #loc
</description>
</problem>
<problem>
<file>InfiniteRecursion.java</file>
<line>78</line>
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Infinite recursion</problem_class>
<description>Method &lt;code&gt;foobarangus()&lt;/code&gt; recurses infinitely, and can only end by throwing an exception #loc
</description>
</problem>
<problem>
<file>InfiniteRecursion.java</file>
<line>126</line>
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Infinite recursion</problem_class>
<description>Method &lt;code&gt;foo1()&lt;/code&gt; recurses infinitely, and can only end by throwing an exception #loc</description>
</problem>
<problem>
<file>InfiniteRecursion.java</file>
<line>132</line>
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Infinite recursion</problem_class>
<description>Method &lt;code&gt;foo2()&lt;/code&gt; recurses infinitely, and can only end by throwing an exception #loc</description>
</problem>
<problem>
<file>InfiniteRecursion.java</file>
<line>138</line>
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Infinite recursion</problem_class>
<description>Method &lt;code&gt;bar1()&lt;/code&gt; recurses infinitely, and can only end by throwing an exception #loc</description>
</problem>
</problems>
@@ -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());
}
}