Merge branch 'pr-112' into pmd/5.4.x
This commit is contained in:
@ -6,6 +6,7 @@ package net.sourceforge.pmd.lang.java.typeresolution.rules;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import net.sourceforge.pmd.lang.ast.Node;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTBlock;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTBlockStatement;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceDeclaration;
|
||||
@ -30,75 +31,81 @@ public class CloneMethodMustImplementCloneable extends AbstractJavaRule {
|
||||
|
||||
@Override
|
||||
public Object visit(ASTClassOrInterfaceDeclaration node, Object data) {
|
||||
ASTImplementsList impl = node.getFirstChildOfType(ASTImplementsList.class);
|
||||
if (impl != null && impl.jjtGetParent().equals(node)) {
|
||||
for (int ix = 0; ix < impl.jjtGetNumChildren(); ix++) {
|
||||
ASTClassOrInterfaceType type = (ASTClassOrInterfaceType) impl.jjtGetChild(ix);
|
||||
if (type.getType() == null) {
|
||||
if ("Cloneable".equals(type.getImage())) {
|
||||
return data;
|
||||
}
|
||||
} else if (type.getType().equals(Cloneable.class)) {
|
||||
return data;
|
||||
} else {
|
||||
List<Class<?>> implementors = Arrays.asList(type.getType().getInterfaces());
|
||||
if (implementors.contains(Cloneable.class)) {
|
||||
return data;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (node.jjtGetNumChildren() != 0 && node.jjtGetChild(0) instanceof ASTExtendsList) {
|
||||
ASTClassOrInterfaceType type = (ASTClassOrInterfaceType) node.jjtGetChild(0).jjtGetChild(0);
|
||||
Class<?> clazz = type.getType();
|
||||
if (clazz != null && clazz.equals(Cloneable.class)) {
|
||||
return data;
|
||||
}
|
||||
while (clazz != null && !Object.class.equals(clazz)) {
|
||||
if (Arrays.asList(clazz.getInterfaces()).contains(Cloneable.class)) {
|
||||
return data;
|
||||
}
|
||||
clazz = clazz.getSuperclass();
|
||||
}
|
||||
}
|
||||
ASTImplementsList impl = node.getFirstChildOfType(ASTImplementsList.class);
|
||||
if (impl != null && impl.jjtGetParent().equals(node)) {
|
||||
for (int ix = 0; ix < impl.jjtGetNumChildren(); ix++) {
|
||||
Node child = impl.jjtGetChild(ix);
|
||||
|
||||
return super.visit(node, data);
|
||||
if (child.getClass() != ASTClassOrInterfaceType.class) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ASTClassOrInterfaceType type = (ASTClassOrInterfaceType) child;
|
||||
if (type.getType() == null) {
|
||||
if ("Cloneable".equals(type.getImage())) {
|
||||
return data;
|
||||
}
|
||||
} else if (type.getType().equals(Cloneable.class)) {
|
||||
return data;
|
||||
} else {
|
||||
List<Class<?>> implementors = Arrays.asList(type.getType().getInterfaces());
|
||||
if (implementors.contains(Cloneable.class)) {
|
||||
return data;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (node.jjtGetNumChildren() != 0 && node.jjtGetChild(0) instanceof ASTExtendsList) {
|
||||
ASTClassOrInterfaceType type = (ASTClassOrInterfaceType) node.jjtGetChild(0).jjtGetChild(0);
|
||||
Class<?> clazz = type.getType();
|
||||
if (clazz != null && clazz.equals(Cloneable.class)) {
|
||||
return data;
|
||||
}
|
||||
while (clazz != null && !Object.class.equals(clazz)) {
|
||||
if (Arrays.asList(clazz.getInterfaces()).contains(Cloneable.class)) {
|
||||
return data;
|
||||
}
|
||||
clazz = clazz.getSuperclass();
|
||||
}
|
||||
}
|
||||
|
||||
return super.visit(node, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object visit(ASTMethodDeclaration node, Object data) {
|
||||
ASTClassOrInterfaceDeclaration classOrInterface = node
|
||||
.getFirstParentOfType(ASTClassOrInterfaceDeclaration.class);
|
||||
if (classOrInterface != null && //Don't analyze enums, which cannot subclass clone()
|
||||
(node.isFinal() || classOrInterface.isFinal())) {
|
||||
if (node.findDescendantsOfType(ASTBlock.class).size() == 1) {
|
||||
List<ASTBlockStatement> blocks = node.findDescendantsOfType(ASTBlockStatement.class);
|
||||
if (blocks.size() == 1) {
|
||||
ASTBlockStatement block = blocks.get(0);
|
||||
ASTClassOrInterfaceType type = block.getFirstDescendantOfType(ASTClassOrInterfaceType.class);
|
||||
if (type != null && type.getType() != null && type.getNthParent(9).equals(node)
|
||||
&& type.getType().equals(CloneNotSupportedException.class)) {
|
||||
return data;
|
||||
} else if (type != null && type.getType() == null
|
||||
&& "CloneNotSupportedException".equals(type.getImage())) {
|
||||
return data;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return super.visit(node, data);
|
||||
ASTClassOrInterfaceDeclaration classOrInterface = node
|
||||
.getFirstParentOfType(ASTClassOrInterfaceDeclaration.class);
|
||||
if (classOrInterface != null && //Don't analyze enums, which cannot subclass clone()
|
||||
(node.isFinal() || classOrInterface.isFinal())) {
|
||||
if (node.findDescendantsOfType(ASTBlock.class).size() == 1) {
|
||||
List<ASTBlockStatement> blocks = node.findDescendantsOfType(ASTBlockStatement.class);
|
||||
if (blocks.size() == 1) {
|
||||
ASTBlockStatement block = blocks.get(0);
|
||||
ASTClassOrInterfaceType type = block.getFirstDescendantOfType(ASTClassOrInterfaceType.class);
|
||||
if (type != null && type.getType() != null && type.getNthParent(9).equals(node)
|
||||
&& type.getType().equals(CloneNotSupportedException.class)) {
|
||||
return data;
|
||||
} else if (type != null && type.getType() == null
|
||||
&& "CloneNotSupportedException".equals(type.getImage())) {
|
||||
return data;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return super.visit(node, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object visit(ASTMethodDeclarator node, Object data) {
|
||||
if (!"clone".equals(node.getImage())) {
|
||||
return data;
|
||||
}
|
||||
int countParams = ((ASTFormalParameters) node.jjtGetChild(0)).jjtGetNumChildren();
|
||||
if (countParams != 0) {
|
||||
return data;
|
||||
}
|
||||
addViolation(data, node);
|
||||
return data;
|
||||
if (!"clone".equals(node.getImage())) {
|
||||
return data;
|
||||
}
|
||||
int countParams = ((ASTFormalParameters) node.jjtGetChild(0)).jjtGetNumChildren();
|
||||
if (countParams != 0) {
|
||||
return data;
|
||||
}
|
||||
addViolation(data, node);
|
||||
return data;
|
||||
}
|
||||
}
|
@ -83,4 +83,12 @@ throw new CloneNotSupportedException();
|
||||
}
|
||||
]]></code>
|
||||
</test-code>
|
||||
|
||||
<test-code>
|
||||
<description>#1534 [java] CloneMethodMustImplementCloneable: ClassCastException with Annotation (java8)</description>
|
||||
<expected-problems>0</expected-problems>
|
||||
<code><![CDATA[
|
||||
public class UnmodifiableList<T> implements @Readonly List<@Readonly T> {}
|
||||
]]></code>
|
||||
</test-code>
|
||||
</test-data>
|
||||
|
@ -161,4 +161,12 @@ public enum Foo {
|
||||
}
|
||||
]]></code>
|
||||
</test-code>
|
||||
|
||||
<test-code>
|
||||
<description>#1534 [java] CloneMethodMustImplementCloneable: ClassCastException with Annotation (java8)</description>
|
||||
<expected-problems>0</expected-problems>
|
||||
<code><![CDATA[
|
||||
public class UnmodifiableList<T> implements @Readonly List<@Readonly T> {}
|
||||
]]></code>
|
||||
</test-code>
|
||||
</test-data>
|
||||
|
@ -14,6 +14,7 @@
|
||||
* [#103](https://github.com/pmd/pmd/pull/103): \[java] \[apex] Fix for 1501: CyclomaticComplexity rule causes OOM when class reporting is disabled
|
||||
* [#110](https://github.com/pmd/pmd/pull/110): \[java] Fix parser error (issue 1530)
|
||||
* [#111](https://github.com/pmd/pmd/pull/111): \[java] Fix BooleanInstantiationRule for Java 8
|
||||
* [#112](https://github.com/pmd/pmd/pull/112): \[java] Fix ClassCastException on CloneMethodMustImplementCloneable
|
||||
|
||||
**Bugfixes:**
|
||||
|
||||
@ -26,6 +27,8 @@
|
||||
* [#1522](https://sourceforge.net/p/pmd/bugs/1522/): \[java] CommentRequired: false positive
|
||||
* java-imports/UnusedImports
|
||||
* [#1529](https://sourceforge.net/p/pmd/bugs/1529/): \[java] UnusedImports: The created rule violation has no class name
|
||||
* java-typeresolution/CloneMethodMustImplementCloneable
|
||||
* [#1534](https://sourceforge.net/p/pmd/bugs/1534/): \[java] CloneMethodMustImplementCloneable: ClassCastException with Annotation (java8)
|
||||
* General
|
||||
* [#1499](https://sourceforge.net/p/pmd/bugs/1499/): \[core] CPD test break PMD 5.5.1 build on Windows
|
||||
* [#1506](https://sourceforge.net/p/pmd/bugs/1506/): \[core] When runing any RuleTst, start/end methods not called
|
||||
|
Reference in New Issue
Block a user