From a30cd217f341e61b12e017b59a8a129283583d61 Mon Sep 17 00:00:00 2001
From: Oleg Sukhodolsky
+ Restricts nested if-else blocks to a specified depth (default = 1). +
+ +| name | +description | +type | +default value | +
|---|---|---|---|
| max | +allowed nesting depth | +Integer | +1 | +
+ To configure the check: +
++<module name="NestedIfDepth"/> ++
+ To configure the check to allow nesting depth 3: +
++<module name="NestedIfDepth"> + <property name="max" value="3"/> +</module> ++
+ com.puppycrawl.tools.checkstyle.checks.coding +
++ TreeWalker +
+ ++ Restricts nested if-else blocks to a specified depth (default = 1). +
+ +| name | +description | +type | +default value | +
|---|---|---|---|
| max | +allowed nesting depth | +Integer | +1 | +
+ To configure the check: +
++<module name="NestedTryDepth"/> ++
+ To configure the check to allow nesting depth 3: +
++<module name="NestedTryDepth"> + <property name="max" value="3"/> +</module> ++
+ com.puppycrawl.tools.checkstyle.checks.coding +
++ TreeWalker +
+ diff --git a/docs/releasenotes.html b/docs/releasenotes.html index dfb87cd3b..31bb2cc37 100644 --- a/docs/releasenotes.html +++ b/docs/releasenotes.html @@ -97,6 +97,10 @@ without overriding method equals(comp.lang.Object) (module coding.CovariantEquals). +diff --git a/src/checkstyle/com/puppycrawl/tools/checkstyle/checks/coding/AbstractNestedDepthCheck.java b/src/checkstyle/com/puppycrawl/tools/checkstyle/checks/coding/AbstractNestedDepthCheck.java new file mode 100644 index 000000000..6a64d3859 --- /dev/null +++ b/src/checkstyle/com/puppycrawl/tools/checkstyle/checks/coding/AbstractNestedDepthCheck.java @@ -0,0 +1,94 @@ +//////////////////////////////////////////////////////////////////////////////// +// checkstyle: Checks Java source code for adherence to a set of rules. +// Copyright (C) 2001-2003 Oliver Burn +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +//////////////////////////////////////////////////////////////////////////////// +package com.puppycrawl.tools.checkstyle.checks.coding; + +import com.puppycrawl.tools.checkstyle.api.Check; +import com.puppycrawl.tools.checkstyle.api.DetailAST; + +/** + * Abstract class which provides helpers functionality for nestedchecks. + * + * @author Simon Harris + */ +public abstract class AbstractNestedDepthCheck extends Check +{ + /** maximum allowed nesting depth */ + private int mMax; + /** curren nesting depth */ + private int mDepth; + + /** + * Creates new instance of checks. + * @param aMax default allowed nesting depth. + */ + public AbstractNestedDepthCheck(int aMax) + { + setMax(aMax); + } + + /** @see Check */ + public final int[] getRequiredTokens() + { + return getDefaultTokens(); + } + + /** @see Check */ + public void beginTree(DetailAST aRootAST) + { + mDepth = 0; + } + + /** + * Getter for maximum allowed nesting depth. + * @return maximum allowed nesting depth. + */ + public final int getMax() + { + return mMax; + } + + /** + * Setter for maximum allowed nesting depth. + * @param aMax maximum allowed nesting depth. + */ + public final void setMax(int aMax) + { + mMax = aMax; + } + + /** + * Increasing current nesting depth. + * @param aAST note which increases nesting. + * @param aMessageId message id for logging error. + */ + protected final void nestIn(DetailAST aAST, String aMessageId) + { + if (mDepth > mMax) { + log(aAST.getLineNo(), aAST.getColumnNo(), aMessageId, + new Integer(mDepth), new Integer(mMax)); + } + ++mDepth; + } + + /** Decreasing current nesting depth */ + protected final void nestOut() + { + --mDepth; + } +} diff --git a/src/checkstyle/com/puppycrawl/tools/checkstyle/checks/coding/NestedIfDepthCheck.java b/src/checkstyle/com/puppycrawl/tools/checkstyle/checks/coding/NestedIfDepthCheck.java new file mode 100644 index 000000000..06941dba9 --- /dev/null +++ b/src/checkstyle/com/puppycrawl/tools/checkstyle/checks/coding/NestedIfDepthCheck.java @@ -0,0 +1,92 @@ +//////////////////////////////////////////////////////////////////////////////// +// checkstyle: Checks Java source code for adherence to a set of rules. +// Copyright (C) 2001-2003 Oliver Burn +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +//////////////////////////////////////////////////////////////////////////////// +package com.puppycrawl.tools.checkstyle.checks.coding; + +import com.puppycrawl.tools.checkstyle.api.DetailAST; +import com.puppycrawl.tools.checkstyle.api.TokenTypes; +import com.puppycrawl.tools.checkstyle.checks.CheckUtils; + +/** + * Restricts nested if-else blocks to a specified depth (default = 1). + * + * @author Simon Harris + */ +public final class NestedIfDepthCheck extends AbstractNestedDepthCheck +{ + /** default allowed nesting depth. */ + private static final int DEFAULT_MAX = 1; + + /** Creates new check instance with default allowed nesting depth */ + public NestedIfDepthCheck() + { + super(DEFAULT_MAX); + } + + /** @see com.puppycrawl.tools.checkstyle.api.Check */ + public int[] getDefaultTokens() + { + return new int[] {TokenTypes.LITERAL_IF}; + } + + /** @see com.puppycrawl.tools.checkstyle.api.Check */ + public void visitToken(DetailAST aAST) + { + switch (aAST.getType()) { + case TokenTypes.LITERAL_IF: + visitLiteralIf(aAST); + break; + default: + throw new IllegalStateException(aAST.toString()); + } + } + + /** @see com.puppycrawl.tools.checkstyle.api.Check */ + public void leaveToken(DetailAST aAST) + { + switch (aAST.getType()) { + case TokenTypes.LITERAL_IF: + leaveLiteralIf(aAST); + break; + default: + throw new IllegalStateException(aAST.toString()); + } + } + + /** + * Increases current nesting depth. + * @param aIf node for if. + */ + private void visitLiteralIf(DetailAST aIf) + { + if (!CheckUtils.isElseIf(aIf)) { + nestIn(aIf, "nested.if.depth"); + } + } + + /** + * Decreases current nesting depth. + * @param aIf node for if. + */ + private void leaveLiteralIf(DetailAST aIf) + { + if (!CheckUtils.isElseIf(aIf)) { + nestOut(); + } + } +} diff --git a/src/checkstyle/com/puppycrawl/tools/checkstyle/checks/coding/NestedTryDepthCheck.java b/src/checkstyle/com/puppycrawl/tools/checkstyle/checks/coding/NestedTryDepthCheck.java new file mode 100644 index 000000000..2721baca9 --- /dev/null +++ b/src/checkstyle/com/puppycrawl/tools/checkstyle/checks/coding/NestedTryDepthCheck.java @@ -0,0 +1,83 @@ +//////////////////////////////////////////////////////////////////////////////// +// checkstyle: Checks Java source code for adherence to a set of rules. +// Copyright (C) 2001-2003 Oliver Burn +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +//////////////////////////////////////////////////////////////////////////////// +package com.puppycrawl.tools.checkstyle.checks.coding; + +import com.puppycrawl.tools.checkstyle.api.DetailAST; +import com.puppycrawl.tools.checkstyle.api.TokenTypes; + +/** + * Restricts nested try-catch-finally blocks to a specified depth (default = 1). + * @author Simon Harris + */ +public final class NestedTryDepthCheck extends AbstractNestedDepthCheck +{ + /** default allowed nesting depth */ + private static final int DEFAULT_MAX = 1; + + /** Creates new check instance with default allowed nesting depth */ + public NestedTryDepthCheck() + { + super(DEFAULT_MAX); + } + + /** @see com.puppycrawl.tools.checkstyle.api.Check */ + public int[] getDefaultTokens() + { + return new int[] {TokenTypes.LITERAL_TRY}; + } + + /** @see com.puppycrawl.tools.checkstyle.api.Check */ + public void visitToken(DetailAST aAST) + { + switch (aAST.getType()) { + case TokenTypes.LITERAL_TRY: + visitLiteralTry(aAST); + break; + default: + throw new IllegalStateException(aAST.toString()); + } + } + + /** @see com.puppycrawl.tools.checkstyle.api.Check */ + public void leaveToken(DetailAST aAST) + { + switch (aAST.getType()) { + case TokenTypes.LITERAL_TRY: + leaveLiteralTry(); + break; + default: + throw new IllegalStateException(aAST.toString()); + } + } + + /** + * Increases current nesting depth. + * @param aTry node for try. + */ + private void visitLiteralTry(DetailAST aTry) + { + nestIn(aTry, "nested.try.depth"); + } + + /** Decreases current nesting depth */ + private void leaveLiteralTry() + { + nestOut(); + } +} diff --git a/src/checkstyle/com/puppycrawl/tools/checkstyle/checks/coding/messages.properties b/src/checkstyle/com/puppycrawl/tools/checkstyle/checks/coding/messages.properties index 99432fc61..ce3562956 100644 --- a/src/checkstyle/com/puppycrawl/tools/checkstyle/checks/coding/messages.properties +++ b/src/checkstyle/com/puppycrawl/tools/checkstyle/checks/coding/messages.properties @@ -26,4 +26,7 @@ redundant.throws.unchecked=Redundant throws: ''{0}'' is unchecked exception. simplify.boolreturn=Conditional logic can be removed. simplify.expression=Expression can be simplified. +nested.if.depth=Nested if-else depth is {0,number,integer} (max allowed is {1,number,integer}). +nested.try.depth=Nested try depth is {0,number,integer} (max allowed is {1,number,integer}). + string.literal.equality=Literal Strings should be compared using equals(), not ''{0}''. diff --git a/src/testinputs/com/puppycrawl/tools/checkstyle/ComplexityCheckTestInput.java b/src/testinputs/com/puppycrawl/tools/checkstyle/ComplexityCheckTestInput.java index 7018487ad..685d0053c 100644 --- a/src/testinputs/com/puppycrawl/tools/checkstyle/ComplexityCheckTestInput.java +++ b/src/testinputs/com/puppycrawl/tools/checkstyle/ComplexityCheckTestInput.java @@ -44,4 +44,4 @@ public class ComplexityCheckTestInput { } } } -} \ No newline at end of file +} diff --git a/src/testinputs/com/puppycrawl/tools/checkstyle/coding/InputNestedIfDepth.java b/src/testinputs/com/puppycrawl/tools/checkstyle/coding/InputNestedIfDepth.java new file mode 100644 index 000000000..afe1451b4 --- /dev/null +++ b/src/testinputs/com/puppycrawl/tools/checkstyle/coding/InputNestedIfDepth.java @@ -0,0 +1,63 @@ +public class InputNestedIfDepth +{ + void foo() { + // nesting == 0 + if (true) { + } + + // nesting == 1 + if (true) { + if (true) { + } + } + + // nesting == 2 + if (true) { + if (true) { + if (true) { + } + } + } + } + + void fooWithElse() { + // nesting == 0 + if (true) { + } else { + } + + // nesting == 1 + if (true) { + if (true) { + } else { + } + } else { + if (false) { + } else { + } + } + + // nesting == 2 + if (true) { + if (true) { + if (true) { + } else { + } + } else { + if (false) { + } else { + } + } + } else { + if (true) { + if (true) { + } else { + } + } else { + if (false) { + } else { + } + } + } + } +} diff --git a/src/testinputs/com/puppycrawl/tools/checkstyle/coding/InputNestedTryDepth.java b/src/testinputs/com/puppycrawl/tools/checkstyle/coding/InputNestedTryDepth.java new file mode 100644 index 000000000..cf0505836 --- /dev/null +++ b/src/testinputs/com/puppycrawl/tools/checkstyle/coding/InputNestedTryDepth.java @@ -0,0 +1,42 @@ +public class InputNestedTryDepth +{ + void foo() { + // nesting == 0 + try { + } catch (Exception e) { + } + + // nesting == 1 + try { + try { + } catch (Exception e) { + } + } catch (Exception e) { + } + + // nesting == 2 + try { + try { + try { + } catch (Exception e) { + } + } catch (Exception e) { + } + } catch (Exception e) { + } + + // nesting == 3 + try { + try { + try { + try { + } catch (Exception e) { + } + } catch (Exception e) { + } + } catch (Exception e) { + } + } catch (Exception e) { + } + } +} diff --git a/src/tests/com/puppycrawl/tools/checkstyle/AllTests.java b/src/tests/com/puppycrawl/tools/checkstyle/AllTests.java index 9332a8729..66dcfe737 100644 --- a/src/tests/com/puppycrawl/tools/checkstyle/AllTests.java +++ b/src/tests/com/puppycrawl/tools/checkstyle/AllTests.java @@ -30,6 +30,8 @@ import com.puppycrawl.tools.checkstyle.checks.coding.IllegalInstantiationCheckTe import com.puppycrawl.tools.checkstyle.checks.coding.InnerAssignmentCheckTest; import com.puppycrawl.tools.checkstyle.checks.coding.MagicNumberCheckTest; import com.puppycrawl.tools.checkstyle.checks.coding.MissingSwitchDefaultCheckTest; +import com.puppycrawl.tools.checkstyle.checks.coding.NestedIfDepthCheckTest; +import com.puppycrawl.tools.checkstyle.checks.coding.NestedTryDepthCheckTest; import com.puppycrawl.tools.checkstyle.checks.coding.RedundantThrowsCheckTest; import com.puppycrawl.tools.checkstyle.checks.coding.SimplifyBooleanExpressionCheckTest; import com.puppycrawl.tools.checkstyle.checks.coding.SimplifyBooleanReturnCheckTest; @@ -131,6 +133,8 @@ public class AllTests { suite.addTest(new TestSuite(MethodNameCheckTest.class)); suite.addTest(new TestSuite(ModifierOrderCheckTest.class)); suite.addTest(new TestSuite(NeedBracesCheckTest.class)); + suite.addTest(new TestSuite(NestedIfDepthCheckTest.class)); + suite.addTest(new TestSuite(NestedTryDepthCheckTest.class)); suite.addTest(new TestSuite(NewlineAtEndOfFileCheckTest.class)); suite.addTest(new TestSuite(NoWhitespaceAfterCheckTest.class)); suite.addTest(new TestSuite(NoWhitespaceBeforeCheckTest.class)); diff --git a/src/tests/com/puppycrawl/tools/checkstyle/checks/coding/NestedIfDepthCheckTest.java b/src/tests/com/puppycrawl/tools/checkstyle/checks/coding/NestedIfDepthCheckTest.java new file mode 100644 index 000000000..31888db37 --- /dev/null +++ b/src/tests/com/puppycrawl/tools/checkstyle/checks/coding/NestedIfDepthCheckTest.java @@ -0,0 +1,33 @@ +package com.puppycrawl.tools.checkstyle.checks.coding; + +import com.puppycrawl.tools.checkstyle.BaseCheckTestCase; +import com.puppycrawl.tools.checkstyle.DefaultConfiguration; + +public class NestedIfDepthCheckTest extends BaseCheckTestCase +{ + public void testDefault() throws Exception + { + final DefaultConfiguration checkConfig = + createCheckConfig(NestedIfDepthCheck.class); + + final String[] expected = { + "17:17: Nested if-else depth is 2 (max allowed is 1).", + "43:17: Nested if-else depth is 2 (max allowed is 1).", + }; + + verify(checkConfig, getPath("coding/InputNestedIfDepth.java"), expected); + } + // checkConfig.addAttribute("max", "2"); + + public void testCustomNestingDepth() throws Exception + { + final DefaultConfiguration checkConfig = + createCheckConfig(NestedIfDepthCheck.class); + checkConfig.addAttribute("max", "2"); + + final String[] expected = { + }; + + verify(checkConfig, getPath("coding/InputNestedIfDepth.java"), expected); + } +} diff --git a/src/tests/com/puppycrawl/tools/checkstyle/checks/coding/NestedTryDepthCheckTest.java b/src/tests/com/puppycrawl/tools/checkstyle/checks/coding/NestedTryDepthCheckTest.java new file mode 100644 index 000000000..38ac9a0d7 --- /dev/null +++ b/src/tests/com/puppycrawl/tools/checkstyle/checks/coding/NestedTryDepthCheckTest.java @@ -0,0 +1,34 @@ +package com.puppycrawl.tools.checkstyle.checks.coding; + +import com.puppycrawl.tools.checkstyle.BaseCheckTestCase; +import com.puppycrawl.tools.checkstyle.DefaultConfiguration; + +public class NestedTryDepthCheckTest extends BaseCheckTestCase +{ + public void testDefault() throws Exception + { + final DefaultConfiguration checkConfig = + createCheckConfig(NestedTryDepthCheck.class); + + final String[] expected = { + "20:17: Nested try depth is 2 (max allowed is 1).", + "31:17: Nested try depth is 2 (max allowed is 1).", + "32:21: Nested try depth is 3 (max allowed is 1).", + }; + + verify(checkConfig, getPath("coding/InputNestedTryDepth.java"), expected); + } + + public void testCustomNestingDepth() throws Exception + { + final DefaultConfiguration checkConfig = + createCheckConfig(NestedTryDepthCheck.class); + checkConfig.addAttribute("max", "2"); + + final String[] expected = { + "32:21: Nested try depth is 3 (max allowed is 2).", + }; + + verify(checkConfig, getPath("coding/InputNestedTryDepth.java"), expected); + } +}