Implementation for NestedIfDepthCheck and NestedTryDepthCheck.

Thanks Simon.
This commit is contained in:
Oleg Sukhodolsky 2003-06-28 20:02:25 +00:00
parent 784842200f
commit a30cd217f3
13 changed files with 560 additions and 2 deletions

View File

@ -120,6 +120,14 @@
<module name="ArrayTrailingComma"/>
<!-- Generates quite a few errors -->
<!-- module name="CyclomaticComplexity"/ -->
<module name="CyclomaticComplexity">
<property name="severity" value="ignore"/>
</module>
<module name="NestedIfDepth">
<property name="max" value="3"/>
</module>
<module name="NestedTryDepth"/>
</module>
</module>

View File

@ -55,6 +55,12 @@
<li>
<a href="#MissingSwitchDefault">MissingSwitchDefault</a>
</li>
<li>
<a href="#NestedIfDepth">NestedIfDepth</a>
</li>
<li>
<a href="#NestedTryDepth">NestedTryDepth</a>
</li>
<li>
<a href="#RedundantThrows">RedundantThrows</a>
</li>
@ -691,6 +697,98 @@ return !valid();
<a href="config.html#treewalker">TreeWalker</a>
</p>
<!-- --> <a name="NestedIfDepth"></a> <h2>NestedIfDepth</h2>
<h4>Description</h4>
<p class="body">
Restricts nested if-else blocks to a specified depth (default = 1).
</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>allowed nesting depth</td>
<td><a href="property_types.html#integer">Integer</a></td>
<td><span class="default">1</span></td>
</tr>
</table>
<h4>Example</h4>
<p class="body">
To configure the check:
</p>
<pre class="body">
&lt;module name=&quot;NestedIfDepth&quot;/&gt;
</pre>
<p class="body">
To configure the check to allow nesting depth 3:
</p>
<pre class="body">
&lt;module name=&quot;NestedIfDepth&quot;&gt;
&lt;property name=&quot;max&quot; value=&quot;3&quot;/&gt;
&lt;/module&gt;
</pre>
<h4>Package</h4>
<p class="body">
com.puppycrawl.tools.checkstyle.checks.coding
</p>
<h4>Parent Module</h4>
<p class="body">
<a href="config.html#treewalker">TreeWalker</a>
</p>
<!-- --> <a name="NestedTryDepth"></a> <h2>NestedTryDepth</h2>
<h4>Description</h4>
<p class="body">
Restricts nested if-else blocks to a specified depth (default = 1).
</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>allowed nesting depth</td>
<td><a href="property_types.html#integer">Integer</a></td>
<td><span class="default">1</span></td>
</tr>
</table>
<h4>Example</h4>
<p class="body">
To configure the check:
</p>
<pre class="body">
&lt;module name=&quot;NestedTryDepth&quot;/&gt;
</pre>
<p class="body">
To configure the check to allow nesting depth 3:
</p>
<pre class="body">
&lt;module name=&quot;NestedTryDepth&quot;&gt;
&lt;property name=&quot;max&quot; value=&quot;3&quot;/&gt;
&lt;/module&gt;
</pre>
<h4>Package</h4>
<p class="body">
com.puppycrawl.tools.checkstyle.checks.coding
</p>
<h4>Parent Module</h4>
<p class="body">
<a href="config.html#treewalker">TreeWalker</a>
</p>
</td>
</tr>
</table>

View File

@ -97,6 +97,10 @@
without overriding method equals(comp.lang.Object)
(module coding.CovariantEquals).</li>
<li class="body">Added NestedTryDepthCheck and
NestedIfDepthCheck from Simon Harris (requests 750736 and
750744).</li>
</ul>
<p class="body">

View File

@ -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 <a href="mailto:simon@redhillconsulting.com.au">Simon Harris</a>
*/
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;
}
}

View File

@ -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 <a href="mailto:simon@redhillconsulting.com.au">Simon Harris</a>
*/
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();
}
}
}

View File

@ -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 <a href="mailto:simon@redhillconsulting.com.au">Simon Harris</a>
*/
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();
}
}

View File

@ -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}''.

View File

@ -44,4 +44,4 @@ public class ComplexityCheckTestInput {
}
}
}
}
}

View File

@ -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 {
}
}
}
}
}

View File

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

View File

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

View File

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

View File

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