Added violation case for InefficientEmptyStringCheckRule
String.trim().isEmpty() now triggers a violation. Fixed checkstyle
This commit is contained in:

committed by
Juan Martín Sotuyo Dodero

parent
59de7a1460
commit
6bf8138aaf
@ -4,19 +4,21 @@
|
|||||||
package net.sourceforge.pmd.lang.java.rule.strings;
|
package net.sourceforge.pmd.lang.java.rule.strings;
|
||||||
|
|
||||||
import net.sourceforge.pmd.lang.ast.Node;
|
import net.sourceforge.pmd.lang.ast.Node;
|
||||||
|
import net.sourceforge.pmd.lang.java.ast.ASTPrimaryExpression;
|
||||||
import net.sourceforge.pmd.lang.java.rule.AbstractInefficientZeroCheck;
|
import net.sourceforge.pmd.lang.java.rule.AbstractInefficientZeroCheck;
|
||||||
import net.sourceforge.pmd.lang.java.symboltable.JavaNameOccurrence;
|
import net.sourceforge.pmd.lang.java.symboltable.JavaNameOccurrence;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This rule finds code which inefficiently determines empty strings. This code
|
* This rule finds code which inefficiently determines empty strings. This code
|
||||||
* <p/>
|
|
||||||
*
|
*
|
||||||
* <pre>
|
* <pre>
|
||||||
* if(str.trim().length()==0){....
|
* if(str.trim().length()==0){....
|
||||||
* </pre>
|
* </pre>
|
||||||
*
|
*
|
||||||
* <p/> is quite inefficient as trim() causes a new String to be created.
|
* <p>
|
||||||
* Smarter code to check for an empty string would be: <p/>
|
* is quite inefficient as trim() causes a new String to be created. Smarter
|
||||||
|
* code to check for an empty string would be:
|
||||||
|
* </p>
|
||||||
*
|
*
|
||||||
* <pre>
|
* <pre>
|
||||||
* Character.isWhitespace(str.charAt(i));
|
* Character.isWhitespace(str.charAt(i));
|
||||||
@ -26,27 +28,39 @@ import net.sourceforge.pmd.lang.java.symboltable.JavaNameOccurrence;
|
|||||||
*/
|
*/
|
||||||
public class InefficientEmptyStringCheckRule extends AbstractInefficientZeroCheck {
|
public class InefficientEmptyStringCheckRule extends AbstractInefficientZeroCheck {
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* Determine if we're dealing with String.length method
|
|
||||||
*
|
|
||||||
* @param occ
|
|
||||||
* The name occurrence
|
|
||||||
* @return true if it's String.length, else false
|
|
||||||
*/
|
|
||||||
public boolean isTargetMethod(JavaNameOccurrence occ) {
|
public boolean isTargetMethod(JavaNameOccurrence occ) {
|
||||||
if (occ.getNameForWhichThisIsAQualifier() != null
|
if (occ.getNameForWhichThisIsAQualifier() != null
|
||||||
&& occ.getNameForWhichThisIsAQualifier().getImage().indexOf("trim") != -1) {
|
&& occ.getNameForWhichThisIsAQualifier().getImage().indexOf("trim") != -1) {
|
||||||
Node pExpression = occ.getLocation().jjtGetParent().jjtGetParent();
|
Node pExpression = occ.getLocation().jjtGetParent().jjtGetParent();
|
||||||
if (pExpression.jjtGetNumChildren() >= 3
|
if (pExpression.jjtGetNumChildren() > 2 && "length".equals(pExpression.jjtGetChild(2).getImage())) {
|
||||||
&& "length".equals(pExpression.jjtGetChild(2).getImage())) {
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public boolean appliesToClassName(String name) {
|
public boolean appliesToClassName(String name) {
|
||||||
return "String".equals(name);
|
return "String".equals(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object visit(ASTPrimaryExpression node, Object data) {
|
||||||
|
|
||||||
|
if (node.jjtGetNumChildren() > 3) {
|
||||||
|
// Check last suffix
|
||||||
|
if (!"isEmpty".equals(node.jjtGetChild(node.jjtGetNumChildren() - 2).getImage())) {
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
Node prevCall = node.jjtGetChild(node.jjtGetNumChildren() - 4);
|
||||||
|
String target = prevCall.jjtGetNumChildren() > 0 ? prevCall.jjtGetChild(0).getImage() : prevCall.getImage();
|
||||||
|
if (target != null && target.indexOf("trim") != -1) {
|
||||||
|
addViolation(data, node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -0,0 +1,21 @@
|
|||||||
|
/**
|
||||||
|
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
|
||||||
|
*/
|
||||||
|
|
||||||
|
package net.sourceforge.pmd.lang.java.rule.strings;
|
||||||
|
|
||||||
|
import net.sourceforge.pmd.testframework.SimpleAggregatorTst;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Clément Fournier (clement.fournier@insa-rennes.fr)
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class InefficientEmptyStringCheckTest extends SimpleAggregatorTst {
|
||||||
|
|
||||||
|
private static final String RULESET = "java-strings";
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setUp() {
|
||||||
|
addRule(RULESET, "InefficientEmptyStringCheck");
|
||||||
|
}
|
||||||
|
}
|
@ -132,4 +132,52 @@ public class Foo {
|
|||||||
}
|
}
|
||||||
]]></code>
|
]]></code>
|
||||||
</test-code>
|
</test-code>
|
||||||
|
<test-code>
|
||||||
|
<description><![CDATA[
|
||||||
|
String.trim().isEmpty() is called, should have failed
|
||||||
|
]]></description>
|
||||||
|
<expected-problems>1</expected-problems>
|
||||||
|
<code><![CDATA[
|
||||||
|
public class Foo {
|
||||||
|
void bar() {
|
||||||
|
String foo = "foo";
|
||||||
|
boolean b = foo.trim().isEmpty();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]]></code>
|
||||||
|
</test-code>
|
||||||
|
|
||||||
|
<test-code>
|
||||||
|
<description><![CDATA[
|
||||||
|
String.trim().isEmpty() is called after a chain call, should have failed
|
||||||
|
]]></description>
|
||||||
|
<expected-problems>2</expected-problems>
|
||||||
|
<code><![CDATA[
|
||||||
|
public class Foo {
|
||||||
|
void bar() {
|
||||||
|
String foo = "foo";
|
||||||
|
boolean b = Arrays.toString(foo.toCharArray()).trim().isEmpty();
|
||||||
|
int i = 2;
|
||||||
|
b = String.valueOf(i).trim().isEmpty();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]]></code>
|
||||||
|
</test-code>
|
||||||
|
|
||||||
|
<test-code>
|
||||||
|
<description><![CDATA[
|
||||||
|
String.trim().isEmpty() is called after a chain call, should have failed twice
|
||||||
|
]]></description>
|
||||||
|
<expected-problems>2</expected-problems>
|
||||||
|
<code><![CDATA[
|
||||||
|
public class Foo {
|
||||||
|
void bar() {
|
||||||
|
String foo = "foo";
|
||||||
|
boolean b = Arrays.toString(foo.toCharArray()).trim().isEmpty();
|
||||||
|
b = String.valueOf(2).trim().isEmpty();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]]></code>
|
||||||
|
</test-code>
|
||||||
|
|
||||||
</test-data>
|
</test-data>
|
||||||
|
Reference in New Issue
Block a user