forked from phoedos/pmd
Merge pull request #3621 from adangel:java-rule-improvements-3
[java] Rule improvements part 3 #3621 * pr-3621: [doc] Update release notes (#3620) [java] CheckSkipResult - use rulechain [java] AvoidUsingOctalValues - use rulechain [java] AvoidMultipleUnaryOperators - remove unnecessary super [java] SwitchDensity - use super.visit [java] SingularField - fix false negative with anonymous classes
This commit is contained in:
@ -25,6 +25,8 @@ This is a {{ site.pmd.release_type }} release.
|
|||||||
* [#3614](https://github.com/pmd/pmd/issues/3614): \[java] JUnitTestsShouldIncludeAssert doesn't consider nested classes
|
* [#3614](https://github.com/pmd/pmd/issues/3614): \[java] JUnitTestsShouldIncludeAssert doesn't consider nested classes
|
||||||
* [#3618](https://github.com/pmd/pmd/issues/3618): \[java] UnusedFormalParameter doesn't consider anonymous classes
|
* [#3618](https://github.com/pmd/pmd/issues/3618): \[java] UnusedFormalParameter doesn't consider anonymous classes
|
||||||
* [#3630](https://github.com/pmd/pmd/issues/3630): \[java] MethodReturnsInternalArray doesn't consider anonymous classes
|
* [#3630](https://github.com/pmd/pmd/issues/3630): \[java] MethodReturnsInternalArray doesn't consider anonymous classes
|
||||||
|
* java-design
|
||||||
|
* [#3620](https://github.com/pmd/pmd/issues/3620): \[java] SingularField doesn't consider anonymous classes defined in non-private fields
|
||||||
* java-errorprone
|
* java-errorprone
|
||||||
* [#3624](https://github.com/pmd/pmd/issues/3624): \[java] TestClassWithoutTestCases reports wrong classes in a file
|
* [#3624](https://github.com/pmd/pmd/issues/3624): \[java] TestClassWithoutTestCases reports wrong classes in a file
|
||||||
* java-performance
|
* java-performance
|
||||||
|
@ -74,16 +74,16 @@ public class SingularFieldRule extends AbstractLombokAwareRule {
|
|||||||
boolean disallowNotAssignment = getProperty(DISALLOW_NOT_ASSIGNMENT);
|
boolean disallowNotAssignment = getProperty(DISALLOW_NOT_ASSIGNMENT);
|
||||||
|
|
||||||
if (!node.isPrivate() || node.isStatic()) {
|
if (!node.isPrivate() || node.isStatic()) {
|
||||||
return data;
|
return super.visit(node, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hasClassLombokAnnotation() || hasIgnoredAnnotation(node)) {
|
if (hasClassLombokAnnotation() || hasIgnoredAnnotation(node)) {
|
||||||
return data;
|
return super.visit(node, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
// lombok.EqualsAndHashCode is a class-level annotation
|
// lombok.EqualsAndHashCode is a class-level annotation
|
||||||
if (hasIgnoredAnnotation((Annotatable) node.getFirstParentOfType(ASTAnyTypeDeclaration.class))) {
|
if (hasIgnoredAnnotation((Annotatable) node.getFirstParentOfType(ASTAnyTypeDeclaration.class))) {
|
||||||
return data;
|
return super.visit(node, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (ASTVariableDeclarator declarator : node.findChildrenOfType(ASTVariableDeclarator.class)) {
|
for (ASTVariableDeclarator declarator : node.findChildrenOfType(ASTVariableDeclarator.class)) {
|
||||||
@ -194,7 +194,7 @@ public class SingularFieldRule extends AbstractLombokAwareRule {
|
|||||||
addViolation(data, node, new Object[] { declaration.getImage() });
|
addViolation(data, node, new Object[] { declaration.getImage() });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return data;
|
return super.visit(node, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isInAssignment(Node potentialStatement) {
|
private boolean isInAssignment(Node potentialStatement) {
|
||||||
|
@ -51,7 +51,6 @@ public class SwitchDensityRule extends AbstractStatisticalJavaRule {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public SwitchDensityRule() {
|
public SwitchDensityRule() {
|
||||||
super();
|
|
||||||
setProperty(MINIMUM_DESCRIPTOR, 10d);
|
setProperty(MINIMUM_DESCRIPTOR, 10d);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -65,7 +64,7 @@ public class SwitchDensityRule extends AbstractStatisticalJavaRule {
|
|||||||
|
|
||||||
SwitchDensity density = new SwitchDensity();
|
SwitchDensity density = new SwitchDensity();
|
||||||
|
|
||||||
node.childrenAccept(this, density);
|
super.visit(node, density);
|
||||||
|
|
||||||
DataPoint point = new DataPoint();
|
DataPoint point = new DataPoint();
|
||||||
point.setNode(node);
|
point.setNode(node);
|
||||||
@ -86,9 +85,7 @@ public class SwitchDensityRule extends AbstractStatisticalJavaRule {
|
|||||||
((SwitchDensity) data).addStatement();
|
((SwitchDensity) data).addStatement();
|
||||||
}
|
}
|
||||||
|
|
||||||
statement.childrenAccept(this, data);
|
return super.visit(statement, data);
|
||||||
|
|
||||||
return data;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -97,7 +94,6 @@ public class SwitchDensityRule extends AbstractStatisticalJavaRule {
|
|||||||
((SwitchDensity) data).addSwitchLabel();
|
((SwitchDensity) data).addSwitchLabel();
|
||||||
}
|
}
|
||||||
|
|
||||||
switchLabel.childrenAccept(this, data);
|
return super.visit(switchLabel, data);
|
||||||
return data;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,8 +15,8 @@ import net.sourceforge.pmd.lang.java.rule.AbstractJavaRule;
|
|||||||
public class AvoidMultipleUnaryOperatorsRule extends AbstractJavaRule {
|
public class AvoidMultipleUnaryOperatorsRule extends AbstractJavaRule {
|
||||||
|
|
||||||
public AvoidMultipleUnaryOperatorsRule() {
|
public AvoidMultipleUnaryOperatorsRule() {
|
||||||
super.addRuleChainVisit(ASTUnaryExpression.class);
|
addRuleChainVisit(ASTUnaryExpression.class);
|
||||||
super.addRuleChainVisit(ASTUnaryExpressionNotPlusMinus.class);
|
addRuleChainVisit(ASTUnaryExpressionNotPlusMinus.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -27,6 +27,7 @@ public class AvoidUsingOctalValuesRule extends AbstractJavaRule {
|
|||||||
|
|
||||||
public AvoidUsingOctalValuesRule() {
|
public AvoidUsingOctalValuesRule() {
|
||||||
definePropertyDescriptor(STRICT_METHODS_DESCRIPTOR);
|
definePropertyDescriptor(STRICT_METHODS_DESCRIPTOR);
|
||||||
|
addRuleChainVisit(ASTLiteral.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -19,6 +19,10 @@ import net.sourceforge.pmd.lang.symboltable.NameOccurrence;
|
|||||||
|
|
||||||
public class CheckSkipResultRule extends AbstractJavaRule {
|
public class CheckSkipResultRule extends AbstractJavaRule {
|
||||||
|
|
||||||
|
public CheckSkipResultRule() {
|
||||||
|
addRuleChainVisit(ASTVariableDeclaratorId.class);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object visit(ASTVariableDeclaratorId node, Object data) {
|
public Object visit(ASTVariableDeclaratorId node, Object data) {
|
||||||
if (!TypeTestUtil.isA(InputStream.class, node.getTypeNode())) {
|
if (!TypeTestUtil.isA(InputStream.class, node.getTypeNode())) {
|
||||||
|
@ -7,16 +7,17 @@
|
|||||||
<test-code>
|
<test-code>
|
||||||
<description>failure case</description>
|
<description>failure case</description>
|
||||||
<expected-problems>1</expected-problems>
|
<expected-problems>1</expected-problems>
|
||||||
|
<expected-linenumbers>3</expected-linenumbers>
|
||||||
<code><![CDATA[
|
<code><![CDATA[
|
||||||
public class Foo {
|
public class Foo {
|
||||||
|
|
||||||
private int x;
|
private int x;
|
||||||
|
|
||||||
int bar(int y) {
|
int bar(int y) {
|
||||||
x = y + 5;
|
x = y + 5;
|
||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]]></code>
|
]]></code>
|
||||||
</test-code>
|
</test-code>
|
||||||
|
|
||||||
@ -190,6 +191,7 @@ public class Foo {
|
|||||||
<test-code>
|
<test-code>
|
||||||
<description>Reuse variable name as params in method calls</description>
|
<description>Reuse variable name as params in method calls</description>
|
||||||
<expected-problems>1</expected-problems>
|
<expected-problems>1</expected-problems>
|
||||||
|
<expected-linenumbers>2</expected-linenumbers>
|
||||||
<code><![CDATA[
|
<code><![CDATA[
|
||||||
public class Foo {
|
public class Foo {
|
||||||
private Integer x = new Integer(1);
|
private Integer x = new Integer(1);
|
||||||
@ -244,6 +246,7 @@ public class Foo {
|
|||||||
<test-code>
|
<test-code>
|
||||||
<description>failure, static</description>
|
<description>failure, static</description>
|
||||||
<expected-problems>1</expected-problems>
|
<expected-problems>1</expected-problems>
|
||||||
|
<expected-linenumbers>2</expected-linenumbers>
|
||||||
<code><![CDATA[
|
<code><![CDATA[
|
||||||
public class Foo {
|
public class Foo {
|
||||||
private int x;
|
private int x;
|
||||||
@ -257,6 +260,7 @@ public class Foo {
|
|||||||
<test-code>
|
<test-code>
|
||||||
<description>failure, second method re-uses class level name</description>
|
<description>failure, second method re-uses class level name</description>
|
||||||
<expected-problems>1</expected-problems>
|
<expected-problems>1</expected-problems>
|
||||||
|
<expected-linenumbers>2</expected-linenumbers>
|
||||||
<code><![CDATA[
|
<code><![CDATA[
|
||||||
public class Foo {
|
public class Foo {
|
||||||
private int x;
|
private int x;
|
||||||
@ -308,6 +312,7 @@ public class Foo {
|
|||||||
<test-code>
|
<test-code>
|
||||||
<description>1409944, fields not used to synchronize should trigger</description>
|
<description>1409944, fields not used to synchronize should trigger</description>
|
||||||
<expected-problems>1</expected-problems>
|
<expected-problems>1</expected-problems>
|
||||||
|
<expected-linenumbers>3</expected-linenumbers>
|
||||||
<code><![CDATA[
|
<code><![CDATA[
|
||||||
public class Foo {
|
public class Foo {
|
||||||
private final Object sync = new Object();
|
private final Object sync = new Object();
|
||||||
@ -365,6 +370,7 @@ public class Foo {
|
|||||||
<description>Not ok, since inner classes are checked</description>
|
<description>Not ok, since inner classes are checked</description>
|
||||||
<rule-property name="checkInnerClasses">true</rule-property>
|
<rule-property name="checkInnerClasses">true</rule-property>
|
||||||
<expected-problems>1</expected-problems>
|
<expected-problems>1</expected-problems>
|
||||||
|
<expected-linenumbers>3</expected-linenumbers>
|
||||||
<code><![CDATA[
|
<code><![CDATA[
|
||||||
public class Foo {
|
public class Foo {
|
||||||
private class Bar {
|
private class Bar {
|
||||||
@ -387,6 +393,7 @@ public class Foo {
|
|||||||
<description>Not ok, violation with first usage = non-assignment</description>
|
<description>Not ok, violation with first usage = non-assignment</description>
|
||||||
<rule-property name="disallowNotAssignment">true</rule-property>
|
<rule-property name="disallowNotAssignment">true</rule-property>
|
||||||
<expected-problems>1</expected-problems>
|
<expected-problems>1</expected-problems>
|
||||||
|
<expected-linenumbers>2</expected-linenumbers>
|
||||||
<code><![CDATA[
|
<code><![CDATA[
|
||||||
public class Foo {
|
public class Foo {
|
||||||
private int x;
|
private int x;
|
||||||
@ -429,6 +436,7 @@ public class Foo {
|
|||||||
<test-code>
|
<test-code>
|
||||||
<description>multiple fields on same line</description>
|
<description>multiple fields on same line</description>
|
||||||
<expected-problems>1</expected-problems>
|
<expected-problems>1</expected-problems>
|
||||||
|
<expected-linenumbers>2</expected-linenumbers>
|
||||||
<code><![CDATA[
|
<code><![CDATA[
|
||||||
public class Foo {
|
public class Foo {
|
||||||
private int x, foo;
|
private int x, foo;
|
||||||
@ -572,6 +580,7 @@ public class Outer {
|
|||||||
<test-code>
|
<test-code>
|
||||||
<description>[java] SingularField: Lombok false positive with annotated inner class</description>
|
<description>[java] SingularField: Lombok false positive with annotated inner class</description>
|
||||||
<expected-problems>1</expected-problems>
|
<expected-problems>1</expected-problems>
|
||||||
|
<expected-linenumbers>9</expected-linenumbers>
|
||||||
<code><![CDATA[
|
<code><![CDATA[
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
@ -751,4 +760,44 @@ public class Foo {
|
|||||||
}
|
}
|
||||||
]]></code>
|
]]></code>
|
||||||
</test-code>
|
</test-code>
|
||||||
|
|
||||||
|
<test-code>
|
||||||
|
<description>failure case with anonymous class</description>
|
||||||
|
<expected-problems>4</expected-problems>
|
||||||
|
<expected-linenumbers>4,13,20,23</expected-linenumbers>
|
||||||
|
<code><![CDATA[
|
||||||
|
public class Foo {
|
||||||
|
void myMethod() {
|
||||||
|
Object o = new Object() {
|
||||||
|
private int x;
|
||||||
|
|
||||||
|
int bar(int y) {
|
||||||
|
x = y + 5;
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
Object field = new Object() {
|
||||||
|
private int x;
|
||||||
|
|
||||||
|
int bar(int y) {
|
||||||
|
x = y + 5;
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
private Object doubleSingular;
|
||||||
|
Object doBar(final int y) {
|
||||||
|
doubleSingular = new Object() {
|
||||||
|
private int x;
|
||||||
|
|
||||||
|
int bar() {
|
||||||
|
x = y + 5;
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return doubleSingular;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]]></code>
|
||||||
|
</test-code>
|
||||||
</test-data>
|
</test-data>
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
<description>Five stmts in one switch case, should be flagged</description>
|
<description>Five stmts in one switch case, should be flagged</description>
|
||||||
<rule-property name="minimum">4</rule-property>
|
<rule-property name="minimum">4</rule-property>
|
||||||
<expected-problems>1</expected-problems>
|
<expected-problems>1</expected-problems>
|
||||||
|
<expected-linenumbers>4</expected-linenumbers>
|
||||||
<code><![CDATA[
|
<code><![CDATA[
|
||||||
// Switch Density = 5.0
|
// Switch Density = 5.0
|
||||||
public class SwitchDensity1 {
|
public class SwitchDensity1 {
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
<test-code>
|
<test-code>
|
||||||
<description>failure case</description>
|
<description>failure case</description>
|
||||||
<expected-problems>1</expected-problems>
|
<expected-problems>1</expected-problems>
|
||||||
|
<expected-linenumbers>8</expected-linenumbers>
|
||||||
<code><![CDATA[
|
<code><![CDATA[
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
|
|
||||||
@ -24,6 +25,7 @@ public class Foo {
|
|||||||
<test-code>
|
<test-code>
|
||||||
<description>failure case but obfuscated</description>
|
<description>failure case but obfuscated</description>
|
||||||
<expected-problems>1</expected-problems>
|
<expected-problems>1</expected-problems>
|
||||||
|
<expected-linenumbers>8</expected-linenumbers>
|
||||||
<code><![CDATA[
|
<code><![CDATA[
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user