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
20 public final class UseStringIsEmptyRule extends AbstractJavaRulechainRule {
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(
29 expr.getLeftOperand(),
30 expr.getRightOperand()
31 )
32 || matchesLengthCheck(
33 expr.getRightOperand(),
34 expr.getLeftOperand()
35 )
36 )
37 ) {
38 asCtx(data).addViolation(expr);
39 }
40 return data;
41 }
42
43 private static boolean isComparison(final ASTInfixExpression expr) {
44 final boolean result;
45 switch (expr.getOperator()) {
46 case EQ:
47 case NE:
48 case GT:
49 case LT:
50 case GE:
51 case LE:
52 result = true;
53 break;
54 default:
55 result = false;
56 break;
57 }
58 return result;
59 }
60
61
62
63
64
65
66
67
68
69 private static boolean matchesLengthCheck(
70 final ASTExpression length,
71 final ASTExpression literal
72 ) {
73 boolean result = false;
74 if (length != null && literal != null && isZeroOrOneLiteral(literal)
75 && length instanceof ASTMethodCall) {
76 final ASTMethodCall call = (ASTMethodCall) length;
77 result = "length".equals(call.getMethodName())
78 && call.getArguments().isEmpty()
79 && call.getQualifier() != null
80 && isStringExpression(call.getQualifier());
81 }
82 return result;
83 }
84
85 private static boolean isZeroOrOneLiteral(final ASTExpression expr) {
86 boolean matches = false;
87 if (expr instanceof ASTNumericLiteral) {
88 final ASTNumericLiteral lit = (ASTNumericLiteral) expr;
89 final String image = lit.getImage();
90 matches = "0".equals(image) || "1".equals(image);
91 }
92 return matches;
93 }
94
95 private static boolean isStringExpression(final ASTExpression expr) {
96 final JTypeMirror type = expr.getTypeMirror();
97 return type.isClassOrInterface()
98 && "java.lang.String".equals(type.toString());
99 }
100 }