|
|
@@ -7,16 +7,11 @@ import java.io.InvalidObjectException;
|
|
|
import java.io.ObjectInputStream;
|
|
|
import java.util.List;
|
|
|
import java.util.Map;
|
|
|
+import net.ranides.assira.rules.utils.ASTUtils;
|
|
|
|
|
|
import net.sourceforge.pmd.lang.ast.Node;
|
|
|
-import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceDeclaration;
|
|
|
import net.sourceforge.pmd.lang.java.ast.ASTConstructorDeclaration;
|
|
|
-import net.sourceforge.pmd.lang.java.ast.ASTFormalParameter;
|
|
|
import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclaration;
|
|
|
-import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclarator;
|
|
|
-import net.sourceforge.pmd.lang.java.ast.ASTName;
|
|
|
-import net.sourceforge.pmd.lang.java.ast.ASTNameList;
|
|
|
-import net.sourceforge.pmd.lang.java.ast.ASTType;
|
|
|
import net.sourceforge.pmd.lang.java.ast.JavaNode;
|
|
|
import net.sourceforge.pmd.lang.java.rule.AbstractJavaRule;
|
|
|
import net.sourceforge.pmd.lang.java.symboltable.JavaNameOccurrence;
|
|
|
@@ -24,20 +19,24 @@ import net.sourceforge.pmd.lang.java.symboltable.VariableNameDeclaration;
|
|
|
import net.sourceforge.pmd.lang.rule.properties.BooleanProperty;
|
|
|
import net.sourceforge.pmd.lang.symboltable.NameOccurrence;
|
|
|
|
|
|
+@SuppressWarnings("OverridableMethodCallInConstructor")
|
|
|
public class UnusedParameterRule extends AbstractJavaRule {
|
|
|
|
|
|
- private static final BooleanProperty CHECKALL_DESCRIPTOR = new BooleanProperty("checkAll",
|
|
|
- "Check all methods, including non-private ones", false, 1.0f);
|
|
|
+ private static final BooleanProperty CHECKALL_DESCRIPTOR = new BooleanProperty(
|
|
|
+ "checkAll", "Check all methods, including non-private ones", false, 1.0f
|
|
|
+ );
|
|
|
|
|
|
public UnusedParameterRule() {
|
|
|
definePropertyDescriptor(CHECKALL_DESCRIPTOR);
|
|
|
}
|
|
|
|
|
|
+ @Override
|
|
|
public Object visit(ASTConstructorDeclaration node, Object data) {
|
|
|
check(node, data);
|
|
|
return data;
|
|
|
}
|
|
|
|
|
|
+ @Override
|
|
|
public Object visit(ASTMethodDeclaration node, Object data) {
|
|
|
if (!node.isPrivate() && !getProperty(CHECKALL_DESCRIPTOR)) {
|
|
|
return data;
|
|
|
@@ -49,64 +48,43 @@ public class UnusedParameterRule extends AbstractJavaRule {
|
|
|
}
|
|
|
|
|
|
private boolean isSerializationMethod(ASTMethodDeclaration node) {
|
|
|
- ASTMethodDeclarator declarator = node.getFirstDescendantOfType(ASTMethodDeclarator.class);
|
|
|
- List<ASTFormalParameter> parameters = declarator.findDescendantsOfType(ASTFormalParameter.class);
|
|
|
- if (node.isPrivate()
|
|
|
- && "readObject".equals(node.getMethodName())
|
|
|
- && parameters.size() == 1
|
|
|
- && throwsOneException(node, InvalidObjectException.class)) {
|
|
|
- ASTType type = parameters.get(0).getTypeNode();
|
|
|
- if (type.getType() == ObjectInputStream.class
|
|
|
- || ObjectInputStream.class.getSimpleName().equals(type.getTypeImage())
|
|
|
- || ObjectInputStream.class.getName().equals(type.getTypeImage())) {
|
|
|
- return true;
|
|
|
- }
|
|
|
- }
|
|
|
- return false;
|
|
|
- }
|
|
|
-
|
|
|
- private boolean throwsOneException(ASTMethodDeclaration node, Class<? extends Throwable> exception) {
|
|
|
- ASTNameList throwsList = node.getThrows();
|
|
|
- if (throwsList != null && throwsList.jjtGetNumChildren() == 1) {
|
|
|
- ASTName n = (ASTName)throwsList.jjtGetChild(0);
|
|
|
- if (n.getType() == exception
|
|
|
- || exception.getSimpleName().equals(n.getImage())
|
|
|
- || exception.getName().equals(n.getImage())) {
|
|
|
- return true;
|
|
|
- }
|
|
|
- }
|
|
|
- return false;
|
|
|
+ return node.isPrivate()
|
|
|
+ && ASTUtils.isMethod(node, "readObject", ObjectInputStream.class)
|
|
|
+ && ASTUtils.throwsOne(node, InvalidObjectException.class);
|
|
|
}
|
|
|
|
|
|
private void check(Node node, Object data) {
|
|
|
Node parent = node.jjtGetParent().jjtGetParent().jjtGetParent();
|
|
|
- if (parent instanceof ASTClassOrInterfaceDeclaration
|
|
|
- && !((ASTClassOrInterfaceDeclaration) parent).isInterface()) {
|
|
|
- Map<VariableNameDeclaration, List<NameOccurrence>> vars = ((JavaNode) node).getScope().getDeclarations(
|
|
|
- VariableNameDeclaration.class);
|
|
|
- for (Map.Entry<VariableNameDeclaration, List<NameOccurrence>> entry : vars.entrySet()) {
|
|
|
- VariableNameDeclaration nameDecl = entry.getKey();
|
|
|
- if (actuallyUsed(nameDecl, entry.getValue())) {
|
|
|
- continue;
|
|
|
- }
|
|
|
- if( nameDecl.getImage().startsWith("$")) {
|
|
|
- continue;
|
|
|
- }
|
|
|
- addViolation(data, nameDecl.getNode(), new Object[] {
|
|
|
- node instanceof ASTMethodDeclaration ? "method" : "constructor", nameDecl.getImage() });
|
|
|
+ if (!ASTUtils.isTypeClass(parent)) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ Map<VariableNameDeclaration, List<NameOccurrence>> vars =
|
|
|
+ ((JavaNode)node).getScope().getDeclarations(VariableNameDeclaration.class);
|
|
|
+
|
|
|
+ for (Map.Entry<VariableNameDeclaration, List<NameOccurrence>> entry : vars.entrySet()) {
|
|
|
+ VariableNameDeclaration name = entry.getKey();
|
|
|
+ if( name.getImage().startsWith("$") || name.getImage().startsWith("_")) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ if (isActuallyUsed(name, entry.getValue())) {
|
|
|
+ continue;
|
|
|
}
|
|
|
+ addViolation(data, name.getNode(), new Object[] {
|
|
|
+ node instanceof ASTMethodDeclaration ? "method" : "constructor",
|
|
|
+ name.getImage()
|
|
|
+ });
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- private boolean actuallyUsed(VariableNameDeclaration nameDecl, List<NameOccurrence> usages) {
|
|
|
+ private boolean isActuallyUsed(VariableNameDeclaration name, List<NameOccurrence> usages) {
|
|
|
for (NameOccurrence occ : usages) {
|
|
|
JavaNameOccurrence jocc = (JavaNameOccurrence) occ;
|
|
|
if (jocc.isOnLeftHandSide()) {
|
|
|
- if (nameDecl.isArray() && jocc.getLocation().jjtGetParent().jjtGetParent().jjtGetNumChildren() > 1) {
|
|
|
+ if (name.isArray() && jocc.getLocation().jjtGetParent().jjtGetParent().jjtGetNumChildren() > 1) {
|
|
|
// array element access
|
|
|
return true;
|
|
|
}
|
|
|
- continue;
|
|
|
} else {
|
|
|
return true;
|
|
|
}
|