1
2
3
4
5 package com.qulice.pmd.rules;
6
7 import net.sourceforge.pmd.lang.java.ast.ASTExpression;
8 import net.sourceforge.pmd.lang.java.ast.ASTInfixExpression;
9 import net.sourceforge.pmd.lang.java.ast.ASTMethodCall;
10 import net.sourceforge.pmd.lang.java.ast.ASTNumericLiteral;
11 import net.sourceforge.pmd.lang.java.rule.AbstractJavaRulechainRule;
12 import net.sourceforge.pmd.lang.java.types.JTypeMirror;
13
14
15
16
17
18
19 public final class UseStringIsEmptyRule extends AbstractJavaRulechainRule {
20
21 public UseStringIsEmptyRule() {
22 super(ASTInfixExpression.class);
23 }
24
25 @Override
26 public Object visit(final ASTInfixExpression expr, final Object data) {
27 if (isComparison(expr)
28 && (matchesLengthCheck(expr.getLeftOperand(), expr.getRightOperand())
29 || matchesLengthCheck(expr.getRightOperand(), expr.getLeftOperand()))
30 ) {
31 asCtx(data).addViolation(expr);
32 }
33 return data;
34 }
35
36 private static boolean isComparison(final ASTInfixExpression expr) {
37 final boolean result;
38 switch (expr.getOperator()) {
39 case EQ:
40 case NE:
41 case GT:
42 case LT:
43 case GE:
44 case LE:
45 result = true;
46 break;
47 default:
48 result = false;
49 break;
50 }
51 return result;
52 }
53
54
55
56
57
58
59
60
61 private static boolean matchesLengthCheck(
62 final ASTExpression length,
63 final ASTExpression literal
64 ) {
65 boolean result = false;
66 if (length != null && literal != null && isZeroOrOneLiteral(literal)
67 && length instanceof ASTMethodCall) {
68 final ASTMethodCall call = (ASTMethodCall) length;
69 result = "length".equals(call.getMethodName())
70 && call.getArguments().isEmpty()
71 && call.getQualifier() != null
72 && isStringExpression(call.getQualifier());
73 }
74 return result;
75 }
76
77 private static boolean isZeroOrOneLiteral(final ASTExpression expr) {
78 boolean matches = false;
79 if (expr instanceof ASTNumericLiteral) {
80 final ASTNumericLiteral lit = (ASTNumericLiteral) expr;
81 final String image = lit.getImage();
82 matches = "0".equals(image) || "1".equals(image);
83 }
84 return matches;
85 }
86
87
88
89
90
91
92 private static boolean isStringExpression(final ASTExpression expr) {
93 final JTypeMirror type = expr.getTypeMirror();
94 return type.isClassOrInterface()
95 && String.class.getName().equals(type.toString());
96 }
97 }