AvoidCallingFinalize: constructor false negative fix

This commit is contained in:
Mykhailo Palahuta
2020-07-16 19:21:22 +03:00
parent 2eedff056c
commit 9bbb6aab4d
2 changed files with 31 additions and 41 deletions

View File

@ -4,11 +4,9 @@
package net.sourceforge.pmd.lang.java.rule.errorprone; package net.sourceforge.pmd.lang.java.rule.errorprone;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import net.sourceforge.pmd.lang.java.ast.ASTBlock;
import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclaration; import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclaration;
import net.sourceforge.pmd.lang.java.ast.ASTPrimaryExpression; import net.sourceforge.pmd.lang.java.ast.ASTPrimaryExpression;
import net.sourceforge.pmd.lang.java.ast.ASTPrimaryPrefix; import net.sourceforge.pmd.lang.java.ast.ASTPrimaryPrefix;
@ -21,57 +19,31 @@ public class AvoidCallingFinalizeRule extends AbstractJavaRule {
private static final Pattern FINALIZE_METHOD_PATTERN = Pattern.compile("^(.+\\.)?finalize$"); private static final Pattern FINALIZE_METHOD_PATTERN = Pattern.compile("^(.+\\.)?finalize$");
@Override @Override
public Object visit(ASTBlock block, Object data) { public Object visit(ASTPrimaryExpression primaryExpression, Object data) {
List<ASTPrimaryExpression> finalizeMethodCalls = getIncorrectFinalizeMethodCalls(block); if (isIncorrectFinalizeMethodCall(primaryExpression)) {
for (ASTPrimaryExpression finalizeMethodCall : finalizeMethodCalls) { addViolation(data, primaryExpression);
addViolation(data, finalizeMethodCall);
} }
return data; return data;
} }
private List<ASTPrimaryExpression> getIncorrectFinalizeMethodCalls(ASTBlock block) { private boolean isIncorrectFinalizeMethodCall(ASTPrimaryExpression primaryExpression) {
if (isFinalizeMethodBlock(block)) { return isFinalizeMethodCall(primaryExpression)
return getNotSuperFinalizeMethodCalls(block); && (isNotInFinalizeMethod(primaryExpression) || isNotSuperMethodCall(primaryExpression));
}
return getFinalizeMethodCalls(block);
} }
private boolean isFinalizeMethodBlock(ASTBlock block) { private boolean isNotInFinalizeMethod(ASTPrimaryExpression primaryExpression) {
ASTMethodDeclaration methodDeclaration = block.getFirstParentOfType(ASTMethodDeclaration.class); ASTMethodDeclaration methodDeclaration = primaryExpression.getFirstParentOfType(ASTMethodDeclaration.class);
return methodDeclaration != null && isFinalizeMethodDeclaration(methodDeclaration); return methodDeclaration == null || isNotFinalizeMethodDeclaration(methodDeclaration);
}
private boolean isNotFinalizeMethodDeclaration(ASTMethodDeclaration methodDeclaration) {
return !isFinalizeMethodDeclaration(methodDeclaration);
} }
private boolean isFinalizeMethodDeclaration(ASTMethodDeclaration methodDeclaration) { private boolean isFinalizeMethodDeclaration(ASTMethodDeclaration methodDeclaration) {
return "finalize".equals(methodDeclaration.getName()) && methodDeclaration.getArity() == 0; return "finalize".equals(methodDeclaration.getName()) && methodDeclaration.getArity() == 0;
} }
private List<ASTPrimaryExpression> getNotSuperFinalizeMethodCalls(ASTBlock block) {
List<ASTPrimaryExpression> finalizeMethodCalls = getFinalizeMethodCalls(block);
List<ASTPrimaryExpression> notSuperCalls = new ArrayList<>();
for (ASTPrimaryExpression finalizeMethodCall : finalizeMethodCalls) {
if (isNotSuperMethodCall(finalizeMethodCall)) {
notSuperCalls.add(finalizeMethodCall);
}
}
return notSuperCalls;
}
private boolean isNotSuperMethodCall(ASTPrimaryExpression primaryExpression) {
ASTPrimaryPrefix primaryPrefix = primaryExpression.getFirstChildOfType(ASTPrimaryPrefix.class);
return primaryPrefix == null || !primaryPrefix.usesSuperModifier();
}
private List<ASTPrimaryExpression> getFinalizeMethodCalls(ASTBlock block) {
List<ASTPrimaryExpression> primaryExpressions = block.findDescendantsOfType(ASTPrimaryExpression.class);
List<ASTPrimaryExpression> finalizeMethodCalls = new ArrayList<>();
for (ASTPrimaryExpression primaryExpression : primaryExpressions) {
if (isFinalizeMethodCall(primaryExpression)) {
finalizeMethodCalls.add(primaryExpression);
}
}
return finalizeMethodCalls;
}
private boolean isFinalizeMethodCall(ASTPrimaryExpression primaryExpression) { private boolean isFinalizeMethodCall(ASTPrimaryExpression primaryExpression) {
return hasFinalizeName(primaryExpression) && getArgsCount(primaryExpression) == 0; return hasFinalizeName(primaryExpression) && getArgsCount(primaryExpression) == 0;
} }
@ -98,4 +70,9 @@ public class AvoidCallingFinalizeRule extends AbstractJavaRule {
} }
return -1; return -1;
} }
private boolean isNotSuperMethodCall(ASTPrimaryExpression primaryExpression) {
ASTPrimaryPrefix primaryPrefix = primaryExpression.getFirstChildOfType(ASTPrimaryPrefix.class);
return primaryPrefix == null || !primaryPrefix.usesSuperModifier();
}
} }

View File

@ -117,6 +117,19 @@ public class Foo {
finalize++; finalize++;
return finalize; return finalize;
} }
}
]]></code>
</test-code>
<test-code>
<description>super.finalize in constructor false-negative test</description>
<expected-problems>1</expected-problems>
<code><![CDATA[
public class Foo {
public Foo() throws Throwable {
super.equals(new String());
super.finalize();
}
} }
]]></code> ]]></code>
</test-code> </test-code>