diff --git a/pmd/etc/changelog.txt b/pmd/etc/changelog.txt index 51d450333b..bdcdccc9ed 100644 --- a/pmd/etc/changelog.txt +++ b/pmd/etc/changelog.txt @@ -6,6 +6,7 @@ Fixed bug 2230809 - False +: ClassWithOnlyPrivateConstructorsShouldBeFinal Fixed bug 2338341 - ArrayIndexOutOfBoundsException in CPD (on Ruby) Fixed bug 2315599 - False +: UseSingleton with class containing constructor Fixed bug 1955852 - false positives for UnusedPrivateMethod & UnusedLocalVariable +Fixed bug 2404700 - UseSingleton should not act on enums October 12, 2008 - 4.2.4: diff --git a/pmd/regress/test/net/sourceforge/pmd/rules/design/xml/UseSingleton.xml b/pmd/regress/test/net/sourceforge/pmd/rules/design/xml/UseSingleton.xml index 653147ae54..b04c300e1e 100644 --- a/pmd/regress/test/net/sourceforge/pmd/rules/design/xml/UseSingleton.xml +++ b/pmd/regress/test/net/sourceforge/pmd/rules/design/xml/UseSingleton.xml @@ -134,6 +134,36 @@ public class UseSingleton extends Exception { } ]]> - - - \ No newline at end of file + + + 1 + + + + + 0 + + + diff --git a/pmd/src/net/sourceforge/pmd/rules/design/UseSingleton.java b/pmd/src/net/sourceforge/pmd/rules/design/UseSingleton.java index c5f7b1b8f9..8f7a078348 100644 --- a/pmd/src/net/sourceforge/pmd/rules/design/UseSingleton.java +++ b/pmd/src/net/sourceforge/pmd/rules/design/UseSingleton.java @@ -4,71 +4,66 @@ package net.sourceforge.pmd.rules.design; import net.sourceforge.pmd.AbstractRule; +import net.sourceforge.pmd.ast.ASTClassOrInterfaceBody; import net.sourceforge.pmd.ast.ASTClassOrInterfaceDeclaration; import net.sourceforge.pmd.ast.ASTClassOrInterfaceType; -import net.sourceforge.pmd.ast.ASTCompilationUnit; import net.sourceforge.pmd.ast.ASTConstructorDeclaration; import net.sourceforge.pmd.ast.ASTFieldDeclaration; import net.sourceforge.pmd.ast.ASTMethodDeclaration; import net.sourceforge.pmd.ast.ASTResultType; +import net.sourceforge.pmd.ast.Node; public class UseSingleton extends AbstractRule { - private boolean isOK; - private int methodCount; + @Override + public Object visit(ASTClassOrInterfaceBody decl, Object data) { + if (decl.jjtGetParent() instanceof ASTClassOrInterfaceDeclaration) { + ASTClassOrInterfaceDeclaration parent = (ASTClassOrInterfaceDeclaration) decl.jjtGetParent(); + if (parent.isAbstract() || parent.isInterface()) { + return super.visit(decl, data); + } + int i = decl.jjtGetNumChildren(); + int methodCount = 0; + boolean isOK = false; + while (i > 0) { + Node n = decl.jjtGetChild(--i).jjtGetChild(0); + if (n instanceof ASTFieldDeclaration) { + if (!((ASTFieldDeclaration) n).isStatic()) { + isOK = true; + break; + } + } else if (n instanceof ASTConstructorDeclaration) { + if (((ASTConstructorDeclaration) n).isPrivate()) { + isOK = true; + break; + } + } else if (n instanceof ASTMethodDeclaration) { + ASTMethodDeclaration m = (ASTMethodDeclaration) n; + if (!m.isPrivate()) { + methodCount++; + } + if (!m.isStatic()) { + isOK = true; + break; + } - public Object visit(ASTCompilationUnit cu, Object data) { - methodCount = 0; - isOK = false; - Object result = cu.childrenAccept(this, data); - if (!isOK && methodCount > 0) { - addViolation(data, cu); - } + // TODO use symbol table + if (m.getMethodName().equals("suite")) { + ASTResultType res = m.getResultType(); + ASTClassOrInterfaceType c = res.getFirstChildOfType(ASTClassOrInterfaceType.class); + if (c != null && c.hasImageEqualTo("Test")) { + isOK = true; + break; + } + } - return result; - } - - public Object visit(ASTFieldDeclaration decl, Object data) { - if (!decl.isStatic()) { - isOK = true; - } - return data; - } - - public Object visit(ASTConstructorDeclaration decl, Object data) { - if (decl.isPrivate()) { - isOK = true; - } - return data; - } - - public Object visit(ASTClassOrInterfaceDeclaration decl, Object data) { - if (decl.isAbstract()) { - isOK = true; + } + } + if (!isOK && methodCount > 0) { + addViolation(data, decl); + } } return super.visit(decl, data); } - public Object visit(ASTMethodDeclaration decl, Object data) { - // Private method does no count - if ( ! decl.isPrivate() ) { - methodCount++; - } - - if (!isOK && !decl.isStatic() ) { - isOK = true; - } - - // TODO use symbol table - if (decl.getMethodName().equals("suite")) { - ASTResultType res = decl.getFirstChildOfType(ASTResultType.class); - ASTClassOrInterfaceType c = res.getFirstChildOfType(ASTClassOrInterfaceType.class); - if (c != null && c.hasImageEqualTo("Test")) { - isOK = true; - } - } - - return data; - } - }