Added ExecutableStatementCount check from Simon Harris (request 750751).

This commit is contained in:
Rick Giles 2003-08-30 21:17:41 +00:00
parent 24c00273b2
commit b8f9b199ad
5 changed files with 377 additions and 0 deletions

View File

@ -24,6 +24,9 @@
<ul>
<li>
<a href="#CyclomaticComplexity">CyclomaticComplexity</a>
<li>
<a href="#ExecutableStatementCount">ExecutableStatementCount</a>
</li>
</li>
</ul>
</td>
@ -96,6 +99,76 @@ considered good, 5-7 ok, 8-10 consider re-factoring, and 11+ re-factor now!
</p>
<!-- --><a name="ExecutableStatementCount"></a> <h2>ExecutableStatementCount</h2>
<h4>Description</h4>
<p class="body">
Restricts the number of executable statements to a specified limit.
</p>
<h4>Properties</h4>
<table width="100%" border="1" cellpadding="5" class="body">
<tr class="header">
<th>name</th>
<th>description</th>
<th>type</th>
<th>default value</th>
</tr>
<tr>
<td>max</td>
<td>the maximum threshold allowed</td>
<td><a href="property_types.html#integer">integer</a></td>
<td><span class="default">30</span></td>
</tr>
<tr>
<td>tokens</td>
<td>members to check</td>
<td>subset of tokens <a
href="api/com/puppycrawl/tools/checkstyle/api/TokenTypes.html#CTOR_DEF">CTOR_DEF</a>,
<a
href="api/com/puppycrawl/tools/checkstyle/api/TokenTypes.html#METHOD_DEF">METHOD_DEF</a>,
<a
href="api/com/puppycrawl/tools/checkstyle/api/TokenTypes.html#INSTANCE_INIT">INSTANCE_INIT</a>,
<a
href="api/com/puppycrawl/tools/checkstyle/api/TokenTypes.html#STATIC_INIT">STATIC_INIT</a>
</td>
<td>all tokens</td>
</tr>
</table>
<h4>Examples</h4>
<p class="body">
To configure the check:
</p>
<pre class="body">
&lt;module name=&quot;ExecutableStatementCount&quot;/&gt;
</pre>
<p class="body">
To configure the check with a threshold of 20 for constructor and
method definitions:
</p>
<pre class="body">
&lt;module name=&quot;ExecutableStatementCount&quot;&gt;
&lt;property name=&quot;max&quot; value=&quot;20&quot;/&gt;
&lt;property name=&quot;tokens&quot; value=&quot;CTOR_DEF,METHOD_DEF&quot;/&gt;
&lt;/module&gt;
</pre>
<h4>Package</h4>
<p class="body">
com.puppycrawl.tools.checkstyle.checks.metrics
</p>
<h4>Parent Module</h4>
<p class="body">
<a href="config.html#treewalker">TreeWalker</a>
</p>
</td>
</tr>

View File

@ -155,6 +155,10 @@
<li class="body">Added ReturnCount check from Simon Harris (request 750745).</li>
<li class="body">Added CyclomaticComplexity check from Simon Harris (request 750756).</li>
<li class="body">Added ExecutableStatementCount check from Simon Harris (request 750751).</li>
</ul>
<p class="body">

View File

@ -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 <code>ExecutableStatementCountCheck</code>. */
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;
}
}
}

View File

@ -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));

View File

@ -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);
}
}