Merge branch 'master' into issue-1325

This commit is contained in:
Juan Martín Sotuyo Dodero
2018-09-08 22:11:35 -03:00
committed by GitHub
4 changed files with 105 additions and 10 deletions
@@ -16,6 +16,7 @@ import net.sourceforge.pmd.lang.java.ast.ASTResultType;
import net.sourceforge.pmd.lang.java.ast.ASTType;
import net.sourceforge.pmd.lang.java.ast.ASTVariableDeclarator;
import net.sourceforge.pmd.lang.java.rule.AbstractJavaRule;
import net.sourceforge.pmd.lang.java.typeresolution.TypeHelper;
import net.sourceforge.pmd.properties.BooleanProperty;
import net.sourceforge.pmd.properties.StringMultiProperty;
@@ -134,12 +135,16 @@ public class LinguisticNamingRule extends AbstractJavaRule {
}
}
private boolean isBooleanType(ASTType node) {
return "boolean".equalsIgnoreCase(node.getTypeImage()) || TypeHelper.isA(node, "java.util.concurrent.atomic.AtomicBoolean");
}
private void checkBooleanMethods(ASTMethodDeclaration node, Object data, String nameOfMethod) {
ASTResultType resultType = node.getResultType();
ASTType t = node.getResultType().getFirstChildOfType(ASTType.class);
if (!resultType.isVoid() && t != null) {
for (String prefix : getProperty(BOOLEAN_METHOD_PREFIXES_PROPERTY)) {
if (hasPrefix(nameOfMethod, prefix) && !"boolean".equalsIgnoreCase(t.getTypeImage())) {
if (hasPrefix(nameOfMethod, prefix) && !isBooleanType(t)) {
addViolationWithMessage(data, node, "Linguistics Antipattern - The method ''{0}'' indicates linguistically it returns a boolean, but it returns ''{1}''",
new Object[] { nameOfMethod, t.getTypeImage() });
}
@@ -147,20 +152,20 @@ public class LinguisticNamingRule extends AbstractJavaRule {
}
}
private void checkField(String typeImage, ASTVariableDeclarator node, Object data) {
private void checkField(ASTType typeNode, ASTVariableDeclarator node, Object data) {
for (String prefix : getProperty(BOOLEAN_FIELD_PREFIXES_PROPERTY)) {
if (hasPrefix(node.getName(), prefix) && !"boolean".equalsIgnoreCase(typeImage)) {
if (hasPrefix(node.getName(), prefix) && !isBooleanType(typeNode)) {
addViolationWithMessage(data, node, "Linguistics Antipattern - The field ''{0}'' indicates linguistically it is a boolean, but it is ''{1}''",
new Object[] { node.getName(), typeImage });
new Object[] { node.getName(), typeNode.getTypeImage() });
}
}
}
private void checkVariable(String typeImage, ASTVariableDeclarator node, Object data) {
private void checkVariable(ASTType typeNode, ASTVariableDeclarator node, Object data) {
for (String prefix : getProperty(BOOLEAN_FIELD_PREFIXES_PROPERTY)) {
if (hasPrefix(node.getName(), prefix) && !"boolean".equalsIgnoreCase(typeImage)) {
if (hasPrefix(node.getName(), prefix) && !isBooleanType(typeNode)) {
addViolationWithMessage(data, node, "Linguistics Antipattern - The variable ''{0}'' indicates linguistically it is a boolean, but it is ''{1}''",
new Object[] { node.getName(), typeImage });
new Object[] { node.getName(), typeNode.getTypeImage() });
}
}
}
@@ -171,7 +176,7 @@ public class LinguisticNamingRule extends AbstractJavaRule {
if (type != null && getProperty(CHECK_FIELDS)) {
List<ASTVariableDeclarator> fields = node.findChildrenOfType(ASTVariableDeclarator.class);
for (ASTVariableDeclarator field : fields) {
checkField(type.getTypeImage(), field, data);
checkField(type, field, data);
}
}
return data;
@@ -183,7 +188,7 @@ public class LinguisticNamingRule extends AbstractJavaRule {
if (type != null && getProperty(CHECK_VARIABLES)) {
List<ASTVariableDeclarator> variables = node.findChildrenOfType(ASTVariableDeclarator.class);
for (ASTVariableDeclarator variable : variables) {
checkVariable(type.getTypeImage(), variable, data);
checkVariable(type, variable, data);
}
}
return data;
@@ -981,7 +981,8 @@ if (foo) { // preferred approach
since="6.7.0"
message="Linguistics Antipattern - Method name and return type is inconsistent linguistically"
class="net.sourceforge.pmd.lang.java.rule.codestyle.LinguisticNamingRule"
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_codestyle.html#linguisticnaming">
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_codestyle.html#linguisticnaming"
typeResolution="true">
<description>
This rule finds Linguistic Naming Antipatterns. It checks for fields, that are named, as if they should
be boolean but have a different type. It also checks for methods, that according to their name, should
@@ -461,6 +461,94 @@ public class BooleanFieldsMethodFP {
public void myMethod() {
Boolean hasLegs;
}
}
]]></code>
</test-code>
<test-code>
<description>#1334 [java] LinguisticNaming should support AtomicBooleans</description>
<expected-problems>0</expected-problems>
<code><![CDATA[
import java.util.concurrent.atomic.AtomicBoolean;
public class AtomicBooleanFP {
private final AtomicBoolean isX = new AtomicBoolean(true);
private final AtomicBoolean hasX = new AtomicBoolean(true);
private final AtomicBoolean canX = new AtomicBoolean(true);
private final AtomicBoolean haveX = new AtomicBoolean(true);
private final AtomicBoolean willX = new AtomicBoolean(true);
private final AtomicBoolean shouldX = new AtomicBoolean(true);
public AtomicBoolean isX() {
return isX;
}
public AtomicBoolean hasX() {
return hasX;
}
public AtomicBoolean canX() {
return canX;
}
public AtomicBoolean haveX() {
return haveX;
}
public AtomicBoolean willX() {
return willX;
}
public AtomicBoolean shouldX() {
return shouldX;
}
public void localVariables() {
AtomicBoolean isX = new AtomicBoolean(true);
AtomicBoolean hasX = new AtomicBoolean(true);
AtomicBoolean canX = new AtomicBoolean(true);
AtomicBoolean haveX = new AtomicBoolean(true);
AtomicBoolean willX = new AtomicBoolean(true);
AtomicBoolean shouldX = new AtomicBoolean(true);
}
}
]]></code>
</test-code>
<test-code>
<description>#1334 [java] LinguisticNaming should support AtomicBooleans false negative</description>
<expected-problems>18</expected-problems>
<code><![CDATA[
import another.pkg.AtomicBoolean;
public class AtomicBooleanFN {
private final AtomicBoolean isX = new AtomicBoolean(true);
private final AtomicBoolean hasX = new AtomicBoolean(true);
private final AtomicBoolean canX = new AtomicBoolean(true);
private final AtomicBoolean haveX = new AtomicBoolean(true);
private final AtomicBoolean willX = new AtomicBoolean(true);
private final AtomicBoolean shouldX = new AtomicBoolean(true);
public AtomicBoolean isX() {
return isX;
}
public AtomicBoolean hasX() {
return hasX;
}
public AtomicBoolean canX() {
return canX;
}
public AtomicBoolean haveX() {
return haveX;
}
public AtomicBoolean willX() {
return willX;
}
public AtomicBoolean shouldX() {
return shouldX;
}
public void localVariables() {
AtomicBoolean isX = new AtomicBoolean(true);
AtomicBoolean hasX = new AtomicBoolean(true);
AtomicBoolean canX = new AtomicBoolean(true);
AtomicBoolean haveX = new AtomicBoolean(true);
AtomicBoolean willX = new AtomicBoolean(true);
AtomicBoolean shouldX = new AtomicBoolean(true);
}
}
]]></code>
</test-code>