Merge branch 'pr-1155'

This commit is contained in:
Andreas Dangel
2018-06-16 19:38:01 +02:00
6 changed files with 117 additions and 27 deletions

View File

@ -27,7 +27,6 @@ This is a minor release.
letting you know exactly which modifiers are redundant at each declaration.
### Fixed Issues
* all
* [#1168](https://github.com/pmd/pmd/issues/1168): \[core] xml renderer schema definitions (#538) break included xslt files
* ecmascript
@ -36,6 +35,7 @@ This is a minor release.
* [#651](https://github.com/pmd/pmd/issues/651): \[java] SwitchStmtsShouldHaveDefault should be aware of enum types
* [#869](https://github.com/pmd/pmd/issues/869): \[java] GuardLogStatement false positive on return statements and Math.log
* java-codestyle
* [#667](https://github.com/pmd/pmd/issues/667): [java] Make AtLeastOneConstructor Lombok-aware
* [#1154](https://github.com/pmd/pmd/pull/1154): [java] CommentDefaultAccessModifierRule FP with nested enums
* [#1158](https://github.com/pmd/pmd/issues/1158): \[java] Fix IdenticalCatchBranches false positive
* xml

View File

@ -4,8 +4,8 @@
package net.sourceforge.pmd.lang.java.rule.bestpractices;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
@ -33,9 +33,7 @@ public class UnusedPrivateMethodRule extends AbstractIgnoredAnnotationRule {
@Override
protected Collection<String> defaultSuppressionAnnotations() {
Collection<String> defaultValues = new ArrayList<>();
defaultValues.add("java.lang.Deprecated");
return defaultValues;
return Collections.singletonList("java.lang.Deprecated");
}
/**

View File

@ -0,0 +1,74 @@
/**
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
*/
package net.sourceforge.pmd.lang.java.rule.codestyle;
import java.util.Arrays;
import java.util.Collection;
import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceDeclaration;
import net.sourceforge.pmd.lang.java.ast.ASTConstructorDeclaration;
import net.sourceforge.pmd.lang.java.ast.ASTFieldDeclaration;
import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclaration;
import net.sourceforge.pmd.lang.java.rule.AbstractIgnoredAnnotationRule;
import net.sourceforge.pmd.lang.java.rule.design.UseUtilityClassRule;
/**
* This rule detects non-static classes with no constructors;
* requiring even the default constructor to be explicit.
* It ignores classes with solely static methods,
* use {@link UseUtilityClassRule} to flag those.
*/
public class AtLeastOneConstructorRule extends AbstractIgnoredAnnotationRule {
public AtLeastOneConstructorRule() {
addRuleChainVisit(ASTClassOrInterfaceDeclaration.class);
}
@Override
protected Collection<String> defaultSuppressionAnnotations() {
return Arrays.asList("lombok.Data",
"lombok.Value",
"lombok.Builder",
"lombok.NoArgsConstructor",
"lombok.RequiredArgsConstructor",
"lombok.AllArgsConstructorAtLeastOneConstructor");
}
@Override
public Object visit(final ASTClassOrInterfaceDeclaration node, final Object data) {
// Ignore interfaces / static classes / classes that have a constructor / classes ignored through annotations
if (node.isInterface() || node.isStatic() || node.hasDescendantOfType(ASTConstructorDeclaration.class)
|| hasIgnoredAnnotation(node)) {
return data;
}
boolean atLeastOneMember = false;
// Do we have any non-static methods?
for (final ASTMethodDeclaration m : node.findDescendantsOfType(ASTMethodDeclaration.class)) {
if (!m.isStatic()) {
addViolation(data, node);
return data;
}
atLeastOneMember = true;
}
// .. or fields?
for (final ASTFieldDeclaration f : node.findDescendantsOfType(ASTFieldDeclaration.class)) {
if (!f.isStatic()) {
addViolation(data, node);
return data;
}
atLeastOneMember = true;
}
// Class has no declared members
if (!atLeastOneMember) {
addViolation(data, node);
}
return data;
}
}

View File

@ -4,8 +4,8 @@
package net.sourceforge.pmd.lang.java.rule.codestyle;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import net.sourceforge.pmd.lang.ast.Node;
@ -26,7 +26,7 @@ public class UnnecessaryConstructorRule extends AbstractIgnoredAnnotationRule {
@Override
protected Collection<String> defaultSuppressionAnnotations() {
return Arrays.asList("javax.inject.Inject");
return Collections.singletonList("javax.inject.Inject");
}
@Override

View File

@ -49,28 +49,15 @@ public abstract class Foo { // should be AbstractFoo
language="java"
since="1.04"
message="Each class should declare at least one constructor"
class="net.sourceforge.pmd.lang.rule.XPathRule"
class="net.sourceforge.pmd.lang.java.rule.codestyle.AtLeastOneConstructorRule"
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_codestyle.html#atleastoneconstructor">
<description>
Each class should declare at least one constructor.
<![CDATA[
Each non-static class should declare at least one constructor.
Classes with solely static members are ignored, refer to [UseUtilityClassRule](pmd_rules_java_design.html#useutilityclass) to detect those.
]]>
</description>
<priority>3</priority>
<properties>
<property name="xpath">
<value>
<![CDATA[
//ClassOrInterfaceDeclaration[
not(ClassOrInterfaceBody/ClassOrInterfaceBodyDeclaration/ConstructorDeclaration)
and
(@Static = 'false')
and
(count(./descendant::MethodDeclaration[@Static = 'true']) < 1)
]
[@Interface='false']
]]>
</value>
</property>
</properties>
<example>
<![CDATA[
public class Foo {

View File

@ -100,8 +100,8 @@ skip classes with only static methods
<expected-problems>0</expected-problems>
<code><![CDATA[
public static class Foo {
public static void method() {}
public static void otherMethods() {}
public static void method() {}
public static void otherMethods() {}
}
]]></code>
</test-code>
@ -113,6 +113,37 @@ public class TestAtLeastOneConstructor {
public void NotStatic() {
System.out.println("This class should have a constructor");
}
}
]]></code>
</test-code>
<test-code>
<description>Ignore classes with lombok-generated constructors</description>
<expected-problems>0</expected-problems>
<code><![CDATA[
import lombok.Value;
@Value
public class TestAtLeastOneConstructor {
}
]]></code>
</test-code>
<test-code>
<description>Report classes with at least one non-static method</description>
<expected-problems>1</expected-problems>
<code><![CDATA[
public class TestAtLeastOneConstructor {
public static void foo() { }
public void bar () { }
}
]]></code>
</test-code>
<test-code>
<description>Report classes with at least one non-static field</description>
<expected-problems>1</expected-problems>
<code><![CDATA[
public class TestAtLeastOneConstructor {
public int bar;
public static void foo() { }
}
]]></code>
</test-code>