1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31 package com.qulice.pmd.rules;
32
33 import java.util.Arrays;
34 import java.util.HashMap;
35 import java.util.List;
36 import java.util.Map;
37 import net.sourceforge.pmd.lang.ast.Node;
38 import net.sourceforge.pmd.lang.java.ast.ASTExpression;
39 import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclaration;
40 import net.sourceforge.pmd.lang.java.ast.ASTReferenceType;
41 import net.sourceforge.pmd.lang.java.ast.ASTResultType;
42 import net.sourceforge.pmd.lang.java.ast.ASTType;
43 import net.sourceforge.pmd.lang.java.ast.ASTVariableDeclaratorId;
44 import net.sourceforge.pmd.lang.java.ast.JavaNode;
45 import net.sourceforge.pmd.lang.java.symboltable.JavaNameOccurrence;
46 import net.sourceforge.pmd.lang.java.symboltable.MethodNameDeclaration;
47 import net.sourceforge.pmd.lang.symboltable.NameOccurrence;
48 import net.sourceforge.pmd.lang.symboltable.Scope;
49
50
51
52
53
54
55 @SuppressWarnings("deprecation")
56 public final class UseStringIsEmptyRule
57 extends net.sourceforge.pmd.lang.java.rule.AbstractInefficientZeroCheck {
58
59 @Override
60 public boolean appliesToClassName(final String name) {
61 return net.sourceforge.pmd.util.StringUtil.isSame(
62 name, "String", true, true, true
63 );
64 }
65
66 @Override
67 public Map<String, List<String>> getComparisonTargets() {
68 final Map<String, List<String>> rules = new HashMap<>();
69 rules.put("<", Arrays.asList("1"));
70 rules.put(">", Arrays.asList("0"));
71 rules.put("==", Arrays.asList("0"));
72 rules.put("!=", Arrays.asList("0"));
73 rules.put(">=", Arrays.asList("0", "1"));
74 rules.put("<=", Arrays.asList("0"));
75 return rules;
76 }
77
78 @Override
79 public boolean isTargetMethod(final JavaNameOccurrence occ) {
80 final NameOccurrence name = occ.getNameForWhichThisIsAQualifier();
81 return name != null && "length".equals(name.getImage());
82 }
83
84 @Override
85 public Object visit(
86 final ASTVariableDeclaratorId variable, final Object data
87 ) {
88 final Node node = variable.getTypeNameNode();
89 if (node instanceof ASTReferenceType) {
90 final Class<?> clazz = variable.getType();
91 final String type = variable.getNameDeclaration().getTypeImage();
92 if (clazz != null && !clazz.isArray()
93 && this.appliesToClassName(type)
94 ) {
95 final List<NameOccurrence> declarations = variable.getUsages();
96 this.checkDeclarations(declarations, data);
97 }
98 }
99 variable.childrenAccept(this, data);
100 return data;
101 }
102
103 @Override
104 public Object visit(
105 final ASTMethodDeclaration declaration, final Object data
106 ) {
107 final ASTResultType result = declaration.getResultType();
108 if (!result.isVoid()) {
109 final ASTType node = (ASTType) result.jjtGetChild(0);
110 final Class<?> clazz = node.getType();
111 final String type = node.getTypeImage();
112 if (clazz != null && !clazz.isArray()
113 && this.appliesToClassName(type)
114 ) {
115 final Scope scope = declaration.getScope().getParent();
116 final MethodNameDeclaration method = new MethodNameDeclaration(
117 declaration.getMethodDeclarator()
118 );
119 final List<NameOccurrence> declarations = scope
120 .getDeclarations(MethodNameDeclaration.class)
121 .get(method);
122 this.checkDeclarations(declarations, data);
123 }
124 }
125 declaration.childrenAccept(this, data);
126 return data;
127 }
128
129
130
131
132
133
134 private void checkDeclarations(
135 final Iterable<NameOccurrence> occurrences, final Object data
136 ) {
137 for (final NameOccurrence occurrence : occurrences) {
138 final JavaNameOccurrence jocc = (JavaNameOccurrence) occurrence;
139 if (this.isTargetMethod(jocc)) {
140 final JavaNode location = jocc.getLocation();
141 final Node expr = location.getFirstParentOfType(
142 ASTExpression.class
143 );
144 this.checkNodeAndReport(
145 data, occurrence.getLocation(), expr.jjtGetChild(0)
146 );
147 }
148 }
149 }
150 }