From 70d96d2c57f52fe0b60352ff38fa6af347ebf365 Mon Sep 17 00:00:00 2001 From: Tom Copeland Date: Thu, 6 May 2004 18:45:24 +0000 Subject: [PATCH] Checking in Will Sargent's ExceptionAsFlowControlRule git-svn-id: https://pmd.svn.sourceforge.net/svnroot/pmd/trunk@2674 51baf565-9d33-0410-a72c-fc3788e3496d --- pmd/etc/changelog.txt | 5 +- .../ExceptionAsFlowControlRuleTest.java | 39 +++++++++++++++ pmd/rulesets/newrules.xml | 25 ++++++++++ .../design/ExceptionAsFlowControlRule.java | 49 +++++++++++++++++++ pmd/xdocs/credits.xml | 1 + 5 files changed, 118 insertions(+), 1 deletion(-) create mode 100644 pmd/regress/test/net/sourceforge/pmd/rules/design/ExceptionAsFlowControlRuleTest.java create mode 100644 pmd/src/net/sourceforge/pmd/rules/design/ExceptionAsFlowControlRule.java diff --git a/pmd/etc/changelog.txt b/pmd/etc/changelog.txt index 2825797bb0..c33fb61ba9 100644 --- a/pmd/etc/changelog.txt +++ b/pmd/etc/changelog.txt @@ -1,3 +1,6 @@ +????, 2004 - 1.8: +New rule: ExceptionAsFlowControlRule + April 22, 2004 - 1.7: Moved development environment to Maven 1.0-RC2. Fixed bug 925840 - Messages were no longer getting variable names plugged in correctly @@ -7,7 +10,7 @@ Implemented RFE 925839 - Added some more detail to the UseSingletonRule. Added an optional 'failuresPropertyName' attribute to the Ant task. Refactored away duplicate copies of XPath rule definitions in regress/, yay! Removed manifest from jar file; it was only there for the Main-class attribute, and it's not very useful now since PMD has several dependencies. - + March 15, 2004 - 1.6: Fixed bug 895661 - XML reports containing error elements no longer have malformed XML. Fixed a bug in UnconditionalIfStatement - it no longer flags things like "if (x==true)". diff --git a/pmd/regress/test/net/sourceforge/pmd/rules/design/ExceptionAsFlowControlRuleTest.java b/pmd/regress/test/net/sourceforge/pmd/rules/design/ExceptionAsFlowControlRuleTest.java new file mode 100644 index 0000000000..a7085e243b --- /dev/null +++ b/pmd/regress/test/net/sourceforge/pmd/rules/design/ExceptionAsFlowControlRuleTest.java @@ -0,0 +1,39 @@ +package test.net.sourceforge.pmd.rules.design; + +import test.net.sourceforge.pmd.testframework.SimpleAggregatorTst; +import test.net.sourceforge.pmd.testframework.TestDescriptor; +import net.sourceforge.pmd.rules.design.NullAssignmentRule; +import net.sourceforge.pmd.rules.design.ExceptionAsFlowControlRule; +import net.sourceforge.pmd.PMD; + +public class ExceptionAsFlowControlRuleTest extends SimpleAggregatorTst { + + public void testAll() { + runTests(new TestDescriptor[] { + new TestDescriptor(TEST1, "failure case", 1, new ExceptionAsFlowControlRule()), + new TestDescriptor(TEST2, "normal throw catch", 0, new ExceptionAsFlowControlRule()) + }); + } + + private static final String TEST1 = + "public class Foo {" + PMD.EOL + + " void bar() {" + PMD.EOL + + " try {" + PMD.EOL + + " try {" + PMD.EOL + + " } catch (Exception e) {" + PMD.EOL + + " throw new WrapperException(e);" + PMD.EOL + + " // this is essentially a GOTO to the WrapperException catch block" + PMD.EOL + + " }" + PMD.EOL + + " } catch (WrapperException e) {" + PMD.EOL + + " // do some more stuff " + PMD.EOL + + " }" + PMD.EOL + + " }" + PMD.EOL + + "}"; + + private static final String TEST2 = + "public class Foo {" + PMD.EOL + + " void bar() {" + PMD.EOL + + " try {} catch (Exception e) {}" + PMD.EOL + + " }" + PMD.EOL + + "}"; +} diff --git a/pmd/rulesets/newrules.xml b/pmd/rulesets/newrules.xml index 246e47527f..e187012f4c 100644 --- a/pmd/rulesets/newrules.xml +++ b/pmd/rulesets/newrules.xml @@ -6,6 +6,31 @@ These are new rules for the next release + + + Using Exceptions as flow control leads to GOTOish code. + + 3 + + + + diff --git a/pmd/src/net/sourceforge/pmd/rules/design/ExceptionAsFlowControlRule.java b/pmd/src/net/sourceforge/pmd/rules/design/ExceptionAsFlowControlRule.java new file mode 100644 index 0000000000..8b8371fac0 --- /dev/null +++ b/pmd/src/net/sourceforge/pmd/rules/design/ExceptionAsFlowControlRule.java @@ -0,0 +1,49 @@ +package net.sourceforge.pmd.rules.design; + +import net.sourceforge.pmd.ast.ASTName; +import net.sourceforge.pmd.ast.Node; +import net.sourceforge.pmd.ast.ASTThrowStatement; +import net.sourceforge.pmd.ast.ASTType; +import net.sourceforge.pmd.ast.ASTCatch; +import net.sourceforge.pmd.ast.ASTTryStatement; +import net.sourceforge.pmd.RuleContext; +import net.sourceforge.pmd.AbstractRule; + +import java.util.Iterator; +import java.util.List; + +/** + * Catches the use of exception statements as a flow control device. + * + * @author Will Sargent + */ +public class ExceptionAsFlowControlRule extends AbstractRule { + public Object visit(ASTThrowStatement node, Object data) { + String throwName = getThrowsName(node); + for (Node parent = node.jjtGetParent(); parent != null; parent = parent.jjtGetParent()) { + if (parent instanceof ASTTryStatement) { + List list = ((ASTTryStatement) parent).getCatchBlocks(); + for (Iterator iter = list.iterator(); iter.hasNext();) { + ASTCatch catchStmt = (ASTCatch) iter.next(); + ASTType type = (ASTType) catchStmt.getFormalParameter().findChildrenOfType(ASTType.class).get(0); + ASTName name = (ASTName) type.findChildrenOfType(ASTName.class).get(0); + if (throwName != null && throwName.equals(name.getImage())) { + ((RuleContext) data).getReport().addRuleViolation(createRuleViolation((RuleContext) data, name.getBeginLine())); + } + } + } + } + return data; + } + + private String getThrowsName(ASTThrowStatement node) { + Node childNode = node; + while (childNode.jjtGetNumChildren() > 0) { + childNode = childNode.jjtGetChild(0); + } + if (childNode instanceof ASTName) { + return ((ASTName) childNode).getImage(); + } + return null; + } +} diff --git a/pmd/xdocs/credits.xml b/pmd/xdocs/credits.xml index d71971582b..52c3598243 100644 --- a/pmd/xdocs/credits.xml +++ b/pmd/xdocs/credits.xml @@ -39,6 +39,7 @@