1
2
3
4 package net.sourceforge.pmd.lang.java.rule.optimizations;
5
6 import java.math.BigInteger;
7
8 import net.sourceforge.pmd.lang.ast.Node;
9 import net.sourceforge.pmd.lang.java.ast.ASTBooleanLiteral;
10 import net.sourceforge.pmd.lang.java.ast.ASTCastExpression;
11 import net.sourceforge.pmd.lang.java.ast.ASTExpression;
12 import net.sourceforge.pmd.lang.java.ast.ASTFieldDeclaration;
13 import net.sourceforge.pmd.lang.java.ast.ASTLiteral;
14 import net.sourceforge.pmd.lang.java.ast.ASTNullLiteral;
15 import net.sourceforge.pmd.lang.java.ast.ASTPrimaryExpression;
16 import net.sourceforge.pmd.lang.java.ast.ASTReferenceType;
17 import net.sourceforge.pmd.lang.java.ast.ASTVariableDeclarator;
18 import net.sourceforge.pmd.lang.java.ast.ASTVariableDeclaratorId;
19 import net.sourceforge.pmd.lang.java.rule.AbstractJavaRule;
20
21
22
23
24
25
26
27
28 public class RedundantFieldInitializerRule extends AbstractJavaRule {
29
30 public RedundantFieldInitializerRule() {
31 addRuleChainVisit(ASTFieldDeclaration.class);
32 }
33
34 public Object visit(ASTFieldDeclaration fieldDeclaration, Object data) {
35
36 if (fieldDeclaration.isFinal()) {
37 return data;
38 }
39
40
41
42 for (ASTVariableDeclarator variableDeclarator : fieldDeclaration
43 .findChildrenOfType(ASTVariableDeclarator.class)) {
44 if (variableDeclarator.jjtGetNumChildren() > 1) {
45 final Node variableInitializer = variableDeclarator.jjtGetChild(1);
46 if (variableInitializer.jjtGetChild(0) instanceof ASTExpression) {
47 final Node expression = variableInitializer.jjtGetChild(0);
48 final Node primaryExpression;
49 if (expression.jjtGetNumChildren() == 1) {
50 if (expression.jjtGetChild(0) instanceof ASTPrimaryExpression) {
51 primaryExpression = expression.jjtGetChild(0);
52 } else if (expression.jjtGetChild(0) instanceof ASTCastExpression
53 && expression.jjtGetChild(0).jjtGetChild(1) instanceof ASTPrimaryExpression) {
54 primaryExpression = expression.jjtGetChild(0).jjtGetChild(1);
55 } else {
56 continue;
57 }
58 } else {
59 continue;
60 }
61 final Node primaryPrefix = primaryExpression.jjtGetChild(0);
62 if (primaryPrefix.jjtGetNumChildren() == 1 && primaryPrefix.jjtGetChild(0) instanceof ASTLiteral) {
63 final ASTLiteral literal = (ASTLiteral) primaryPrefix.jjtGetChild(0);
64 if (isRef(fieldDeclaration, variableDeclarator)) {
65
66 if (literal.jjtGetNumChildren() == 1 && literal.jjtGetChild(0) instanceof ASTNullLiteral) {
67 addViolation(data, variableDeclarator);
68 }
69 } else {
70
71 if (literal.jjtGetNumChildren() == 1 && literal.jjtGetChild(0) instanceof ASTBooleanLiteral) {
72
73 ASTBooleanLiteral booleanLiteral = (ASTBooleanLiteral) literal.jjtGetChild(0);
74 if (!booleanLiteral.isTrue()) {
75 addViolation(data, variableDeclarator);
76 }
77 } else if (literal.jjtGetNumChildren() == 0) {
78
79
80
81
82 Number value = -1;
83 if (literal.isIntLiteral()) {
84 value = parseInteger(literal.getImage());
85 } else if (literal.isLongLiteral()) {
86 String s = literal.getImage();
87
88
89 s = s.substring(0, s.length() - 1);
90 value = parseInteger(s);
91 } else if (literal.isFloatLiteral()) {
92 String s = literal.getImage();
93
94
95 s = s.substring(0, s.length() - 1);
96 value = Float.valueOf(s);
97 } else if (literal.isDoubleLiteral()) {
98 value = Double.valueOf(literal.getImage());
99 } else if (literal.isCharLiteral()) {
100 value = (int) literal.getImage().charAt(1);
101 }
102
103 if (value.intValue() == 0) {
104 addViolation(data, variableDeclarator);
105 }
106 }
107 }
108 }
109 }
110 }
111 }
112
113 return data;
114 }
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139 private boolean isRef(ASTFieldDeclaration fieldDeclaration, ASTVariableDeclarator variableDeclarator) {
140 Node type = fieldDeclaration.jjtGetChild(0).jjtGetChild(0);
141 if (type instanceof ASTReferenceType) {
142
143 return true;
144 } else {
145
146 return ((ASTVariableDeclaratorId) variableDeclarator.jjtGetChild(0)).isArray();
147 }
148 }
149
150 private void addViolation(Object data, ASTVariableDeclarator variableDeclarator) {
151 super.addViolation(data, variableDeclarator, variableDeclarator.jjtGetChild(0).getImage());
152 }
153
154 private Number parseInteger(String s) {
155 boolean negative = false;
156 String number = s;
157 if (number.charAt(0) == '-') {
158 negative = true;
159 number = number.substring(1);
160 }
161 BigInteger result;
162 if (number.startsWith("0x") || number.startsWith("0X")) {
163 result = new BigInteger(number.substring(2).replaceAll("_", ""), 16);
164 } else if (number.startsWith("0b") || number.startsWith("0B")) {
165 result = new BigInteger(number.substring(2).replaceAll("_", ""), 8);
166 } else if (number.charAt(0) == '0' && number.length() > 1) {
167 result = new BigInteger(number.substring(1).replaceAll("_", ""), 8);
168 } else {
169 result = new BigInteger(number.replaceAll("_", ""));
170 }
171 if (negative) {
172 result = result.negate();
173 }
174 return result;
175 }
176 }