From b8f9b199ad7de16619cec1f288bd751fad8bc4a9 Mon Sep 17 00:00:00 2001 From: Rick Giles Date: Sat, 30 Aug 2003 21:17:41 +0000 Subject: [PATCH] Added ExecutableStatementCount check from Simon Harris (request 750751). --- docs/config_metrics.html | 73 +++++++ docs/releasenotes.html | 4 + .../ExecutableStatementCountCheck.java | 205 ++++++++++++++++++ .../puppycrawl/tools/checkstyle/AllTests.java | 2 + .../ExecutableStatementCountCheckTest.java | 93 ++++++++ 5 files changed, 377 insertions(+) create mode 100644 src/checkstyle/com/puppycrawl/tools/checkstyle/checks/metrics/ExecutableStatementCountCheck.java create mode 100644 src/tests/com/puppycrawl/tools/checkstyle/checks/metrics/ExecutableStatementCountCheckTest.java diff --git a/docs/config_metrics.html b/docs/config_metrics.html index 5a3a0bfc5..05db9aebc 100644 --- a/docs/config_metrics.html +++ b/docs/config_metrics.html @@ -24,6 +24,9 @@ @@ -96,6 +99,76 @@ considered good, 5-7 ok, 8-10 consider re-factoring, and 11+ re-factor now!

+

ExecutableStatementCount

+

Description

+ +

+ Restricts the number of executable statements to a specified limit. +

+ + +

Properties

+ + + + + + + + + + + + + + + + + + + + + + +
namedescriptiontypedefault value
maxthe maximum threshold allowedinteger30
tokensmembers to checksubset of tokens CTOR_DEF, + METHOD_DEF, + INSTANCE_INIT, + STATIC_INIT + all tokens
+ +

Examples

+

+ To configure the check: +

+
+<module name="ExecutableStatementCount"/>
+      
+

+ To configure the check with a threshold of 20 for constructor and + method definitions: +

+
+<module name="ExecutableStatementCount">
+    <property name="max" value="20"/>
+    <property name="tokens" value="CTOR_DEF,METHOD_DEF"/>
+</module>
+      
+      
+ +

Package

+

+ com.puppycrawl.tools.checkstyle.checks.metrics +

+ +

Parent Module

+

+ TreeWalker +

+ diff --git a/docs/releasenotes.html b/docs/releasenotes.html index 433a8e96b..fea689521 100644 --- a/docs/releasenotes.html +++ b/docs/releasenotes.html @@ -155,6 +155,10 @@
  • Added ReturnCount check from Simon Harris (request 750745).
  • +
  • Added CyclomaticComplexity check from Simon Harris (request 750756).
  • + +
  • Added ExecutableStatementCount check from Simon Harris (request 750751).
  • +

    diff --git a/src/checkstyle/com/puppycrawl/tools/checkstyle/checks/metrics/ExecutableStatementCountCheck.java b/src/checkstyle/com/puppycrawl/tools/checkstyle/checks/metrics/ExecutableStatementCountCheck.java new file mode 100644 index 000000000..26a9102fb --- /dev/null +++ b/src/checkstyle/com/puppycrawl/tools/checkstyle/checks/metrics/ExecutableStatementCountCheck.java @@ -0,0 +1,205 @@ +//////////////////////////////////////////////////////////////////////////////// +// 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.metrics; + +import java.util.Stack; + +import com.puppycrawl.tools.checkstyle.api.Check; +import com.puppycrawl.tools.checkstyle.api.DetailAST; +import com.puppycrawl.tools.checkstyle.api.TokenTypes; + +/** + * Restricts the number of executable statements to a specified limit + * (default = 30). + * @author Simon Harris + */ +public final class ExecutableStatementCountCheck + extends Check +{ + /** default threshold */ + private static final int DEFAULT_MAX = 30; + + /** threshold to report error for */ + private int mMax; + + /** Stack of method contexts. */ + private final Stack mContextStack = new Stack(); + + /** Current method context. */ + private Context mContext; + + /** Constructs a ExecutableStatementCountCheck. */ + public ExecutableStatementCountCheck() + { + setMax(DEFAULT_MAX); + } + + /** @see com.puppycrawl.tools.checkstyle.api.Check#getDefaultTokens() */ + public int[] getDefaultTokens() + { + return new int[] { + TokenTypes.CTOR_DEF, + TokenTypes.METHOD_DEF, + TokenTypes.INSTANCE_INIT, + TokenTypes.STATIC_INIT, + TokenTypes.SLIST, + }; + } + + /** @see com.puppycrawl.tools.checkstyle.api.Check#getRequiredTokens() */ + public int[] getRequiredTokens() + { + return new int[] {TokenTypes.SLIST}; + } + + /** + * Gets the maximum threshold. + * @return the maximum threshold. + */ + public int getMax() + { + return mMax; + } + + /** + * Sets the maximum threshold. + * @param aMax the maximum threshold. + */ + public void setMax(int aMax) + { + mMax = aMax; + } + + /** @see com.puppycrawl.tools.checkstyle.api.Check */ + public void beginTree(DetailAST aRootAST) + { + mContext = null; + mContextStack.clear(); + } + + /** @see com.puppycrawl.tools.checkstyle.api.Check */ + public void visitToken(DetailAST aAST) + { + switch (aAST.getType()) { + case TokenTypes.CTOR_DEF: + case TokenTypes.METHOD_DEF: + case TokenTypes.INSTANCE_INIT: + case TokenTypes.STATIC_INIT: + visitMethodDef(); + break; + case TokenTypes.SLIST: + visitSlist(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.CTOR_DEF: + case TokenTypes.METHOD_DEF: + case TokenTypes.INSTANCE_INIT: + case TokenTypes.STATIC_INIT: + leaveMethodDef(aAST); + break; + case TokenTypes.SLIST: + // Do nothing + break; + default: + throw new IllegalStateException(aAST.toString()); + } + } + + /** Process the start of the method definition. */ + private void visitMethodDef() + { + mContextStack.push(mContext); + mContext = new Context(); + } + + /** + * Process the end of a method definition. + * + * @param aAST the token representing the method definition. + */ + private void leaveMethodDef(DetailAST aAST) + { + final int count = mContext.getCount(); + if (count > getMax()) { + log( + aAST.getLineNo(), + aAST.getColumnNo(), + "executableStatementCount", + new Integer(count), + new Integer(getMax())); + } + mContext = (Context) mContextStack.pop(); + } + + /** + * Process the end of a statement list. + * + * @param aAST the token representing the statement list. + */ + private void visitSlist(DetailAST aAST) + { + if (mContext != null) { + mContext.addCount(aAST.getChildCount() / 2); + } + } + + /** + * Class to encapsulate counting information about one member. + * @author Simon Harris + */ + private class Context + { + /** Counter for context elements. */ + private int mCount; + + /** + * Creates new method context. + */ + public Context() + { + mCount = 0; + } + + /** + * Increase count. + * @param aCount the count increment. + */ + public void addCount(int aCount) + { + mCount += aCount; + } + + /** + * Gets the count. + * @return the count. + */ + public int getCount() + { + return mCount; + } + } +} diff --git a/src/tests/com/puppycrawl/tools/checkstyle/AllTests.java b/src/tests/com/puppycrawl/tools/checkstyle/AllTests.java index dbe389da1..85c128b4d 100644 --- a/src/tests/com/puppycrawl/tools/checkstyle/AllTests.java +++ b/src/tests/com/puppycrawl/tools/checkstyle/AllTests.java @@ -73,6 +73,7 @@ import com.puppycrawl.tools.checkstyle.checks.javadoc.JavadocTypeCheckTest; import com.puppycrawl.tools.checkstyle.checks.javadoc.JavadocVariableCheckTest; import com.puppycrawl.tools.checkstyle.checks.javadoc.PackageHtmlCheckTest; import com.puppycrawl.tools.checkstyle.checks.metrics.CyclomaticComplexityCheckTest; +import com.puppycrawl.tools.checkstyle.checks.metrics.ExecutableStatementCountCheckTest; import com.puppycrawl.tools.checkstyle.checks.naming.AbstractClassNameCheckTest; import com.puppycrawl.tools.checkstyle.checks.naming.ConstantNameCheckTest; import com.puppycrawl.tools.checkstyle.checks.naming.LocalFinalVariableNameCheckTest; @@ -196,6 +197,7 @@ public class AllTests { suite.addTest(new TestSuite(RightCurlyCheckTest.class)); suite.addTest(new TestSuite(SimplifyBooleanExpressionCheckTest.class)); suite.addTest(new TestSuite(SimplifyBooleanReturnCheckTest.class)); + suite.addTest(new TestSuite(ExecutableStatementCountCheckTest.class)); suite.addTest(new TestSuite(StaticVariableNameCheckTest.class)); suite.addTest(new TestSuite(StringArrayReaderTest.class)); suite.addTest(new TestSuite(StringLiteralEqualityCheckTest.class)); diff --git a/src/tests/com/puppycrawl/tools/checkstyle/checks/metrics/ExecutableStatementCountCheckTest.java b/src/tests/com/puppycrawl/tools/checkstyle/checks/metrics/ExecutableStatementCountCheckTest.java new file mode 100644 index 000000000..92eabc2d5 --- /dev/null +++ b/src/tests/com/puppycrawl/tools/checkstyle/checks/metrics/ExecutableStatementCountCheckTest.java @@ -0,0 +1,93 @@ +package com.puppycrawl.tools.checkstyle.checks.metrics; + +import com.puppycrawl.tools.checkstyle.BaseCheckTestCase; +import com.puppycrawl.tools.checkstyle.DefaultConfiguration; + +public class ExecutableStatementCountCheckTest + extends BaseCheckTestCase +{ + public void testMaxZero() throws Exception + { + final DefaultConfiguration checkConfig = + createCheckConfig(ExecutableStatementCountCheck.class); + + checkConfig.addAttribute("max", "0"); + + final String[] expected = { + "4:5: Executable statement count is 3 (max allowed is 0).", + "7:17: Executable statement count is 1 (max allowed is 0).", + "17:5: Executable statement count is 2 (max allowed is 0).", + "27:5: Executable statement count is 1 (max allowed is 0).", + "34:5: Executable statement count is 3 (max allowed is 0).", + "48:5: Executable statement count is 2 (max allowed is 0).", + "58:5: Executable statement count is 2 (max allowed is 0).", + "67:5: Executable statement count is 2 (max allowed is 0).", + }; + + verify(checkConfig, getPath("ComplexityCheckTestInput.java"), expected); + } + + public void testMethodDef() throws Exception + { + final DefaultConfiguration checkConfig = + createCheckConfig(ExecutableStatementCountCheck.class); + + checkConfig.addAttribute("max", "0"); + checkConfig.addAttribute("tokens", "METHOD_DEF"); + + final String[] expected = { + "4:5: Executable statement count is 3 (max allowed is 0).", + "7:17: Executable statement count is 1 (max allowed is 0).", + "17:5: Executable statement count is 2 (max allowed is 0).", + "27:5: Executable statement count is 1 (max allowed is 0).", + "34:5: Executable statement count is 3 (max allowed is 0).", + }; + + verify(checkConfig, getPath("ComplexityCheckTestInput.java"), expected); + } + + public void testCtorDef() throws Exception + { + final DefaultConfiguration checkConfig = + createCheckConfig(ExecutableStatementCountCheck.class); + + checkConfig.addAttribute("max", "0"); + checkConfig.addAttribute("tokens", "CTOR_DEF"); + + final String[] expected = { + "48:5: Executable statement count is 2 (max allowed is 0).", + }; + + verify(checkConfig, getPath("ComplexityCheckTestInput.java"), expected); + } + + public void testStaticInit() throws Exception + { + final DefaultConfiguration checkConfig = + createCheckConfig(ExecutableStatementCountCheck.class); + + checkConfig.addAttribute("max", "0"); + checkConfig.addAttribute("tokens", "STATIC_INIT"); + + final String[] expected = { + "58:5: Executable statement count is 2 (max allowed is 0).", + }; + + verify(checkConfig, getPath("ComplexityCheckTestInput.java"), expected); + } + + public void testInstanceInit() throws Exception + { + final DefaultConfiguration checkConfig = + createCheckConfig(ExecutableStatementCountCheck.class); + + checkConfig.addAttribute("max", "0"); + checkConfig.addAttribute("tokens", "INSTANCE_INIT"); + + final String[] expected = { + "67:5: Executable statement count is 2 (max allowed is 0).", + }; + + verify(checkConfig, getPath("ComplexityCheckTestInput.java"), expected); + } +} \ No newline at end of file