Clover coverage report - PMD - 3.9 Coverage timestamp: Tue Dec 19 2006 09:38:44 EST FRAMES NO FRAMES |
file stats: | LOC: | 67 |  | Methods: | 2
| NCLOC: | 40 |  | Classes: | 1
Source file | Conditionals | Statements | Methods | TOTAL
UselessOperationOnImmutable.java | 100% | 100% | 100% | 100% |

1 |  | package net.sourceforge.pmd.rules;
2 |  |
3 |  | import java.util.Iterator;
4 |  | import java.util.Set;
5 |  |
6 |  | import net.sourceforge.pmd.AbstractRule;
7 |  | import net.sourceforge.pmd.ast.ASTExpression;
8 |  | import net.sourceforge.pmd.ast.ASTLocalVariableDeclaration;
9 |  | import net.sourceforge.pmd.ast.ASTName;
10 |  | import net.sourceforge.pmd.ast.ASTType;
11 |  | import net.sourceforge.pmd.ast.ASTVariableDeclaratorId;
12 |  | import net.sourceforge.pmd.symboltable.NameOccurrence;
13 |  | import net.sourceforge.pmd.util.CollectionUtil;
14 |  |
15 |  | /**
16 |  | * An operation on an Immutable object (BigDecimal or BigInteger) won't change
17 |  | * the object itself. The result of the operation is a new object. Therefore,
18 |  | * ignoring the operation result is an error.
19 |  | */
20 |  | public class UselessOperationOnImmutable extends AbstractRule {
21 |  |
22 |  | /**
23 |  | * These are the methods which are immutable
24 |  | */
25 |  | private static final Set targetMethods = CollectionUtil.asSet(new String[] { ".add", ".multiply", ".divide", ".subtract", ".setScale", ".negate", ".movePointLeft", ".movePointRight", ".pow", ".shiftLeft", ".shiftRight" });
26 |  |
27 |  | /**
28 |  | * These are the classes that the rule can apply to
29 |  | */
30 |  | private static final Set targetClasses = CollectionUtil.asSet(new String[] { "java.math.BigDecimal", "BigDecimal", "java.math.BigInteger", "BigInteger" });
31 |  |
32 | 6 | public Object visit(ASTLocalVariableDeclaration node, Object data) {
33 |  |
34 | 6 | ASTVariableDeclaratorId var = getDeclaration(node);
35 | 6 | if (var == null) {
36 | 2 | return super.visit(node, data);
37 |  | }
38 | 4 | String variableName = var.getImage();
39 | 4 | for (Iterator it = var.getUsages().iterator(); it.hasNext();) {
40 | 5 | NameOccurrence no = (NameOccurrence) it.next();
41 | 5 | ASTName sn = (ASTName) no.getLocation();
42 | 5 | if (!sn.jjtGetParent().jjtGetParent().jjtGetParent().getClass().equals(ASTExpression.class)) {
43 | 3 | String methodCall = sn.getImage().substring(variableName.length());
44 | 3 | if (targetMethods.contains(methodCall)) {
45 | 2 | addViolation(data, sn);
46 |  | }
47 |  | }
48 |  | }
49 | 4 | return super.visit(node, data);
50 |  | }
51 |  |
52 |  | /**
53 |  | * This method checks the variable declaration if it is on a class we care
54 |  | * about. If it is, it returns the DeclaratorId
55 |  | *
56 |  | * @param node
57 |  | * The ASTLocalVariableDeclaration which is a problem
58 |  | * @return ASTVariableDeclaratorId
59 |  | */
60 | 6 | private ASTVariableDeclaratorId getDeclaration(ASTLocalVariableDeclaration node) {
61 | 6 | ASTType type = node.getTypeNode();
62 | 6 | if (targetClasses.contains(type.getTypeImage())) {
63 | 4 | return (ASTVariableDeclaratorId) node.jjtGetChild(1).jjtGetChild(0);
64 |  | }
65 | 2 | return null;
66 |  | }
67 |  | }