bug-750348: added check for typecast parens. Involved

a bit of refactoring.
This commit is contained in:
Oliver Burn 2003-06-09 06:20:19 +00:00
parent 75a289111e
commit 99ed7a7d2c
10 changed files with 304 additions and 67 deletions

View File

@ -88,6 +88,7 @@
</module>
<module name="ParameterNumber"/>
<module name="ParenPad"/>
<module name="TypecastParenPad"/>
<module name="RedundantImport"/>
<module name="RedundantModifier"/>
<module name="RightCurly">

View File

@ -37,6 +37,9 @@
<li>
<a href="#ParenPad">ParenPad</a>
</li>
<li>
<a href="#TypecastParenPad">TypecastParenPad</a>
</li>
<li>
<a href="#TabCharacter">TabCharacter</a>
</li>
@ -427,6 +430,8 @@
<p class="body">
<a href="config.html#treewalker">TreeWalker</a>
</p>
<a name="ParenPad"></a> <h2>ParenPad</h2> <h4>Description</h4>
<p class="body">
@ -505,6 +510,73 @@
<a href="config.html#treewalker">TreeWalker</a>
</p>
<a name="TypecastParenPad"></a>
<h2>TypecastParenPad</h2>
<h4>Description</h4>
<p class="body"> Checks the policy on the padding of parentheses for
typecasts. That is, whether a space is required after a left parenthesis
and before a right parenthesis, or such spaces are forbidden. </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>option</td>
<td>policy on how to pad parentheses</td>
<td><a href="property_types.html#parenPad">pad policy</a></td>
<td><span class="default">nospace</span></td>
</tr>
<tr>
<td>tokens</td>
<td>tokens to check</td>
<td>Must have tokens
<a
href="api/com/puppycrawl/tools/checkstyle/api/TokenTypes.html#TYPECAST">TYPECAST</a>,
<a
href="api/com/puppycrawl/tools/checkstyle/api/TokenTypes.html#RPAREN">RPAREN</a>
<td><a
href="api/com/puppycrawl/tools/checkstyle/api/TokenTypes.html#TYPECAST">TYPECAST</a>,
<a
href="api/com/puppycrawl/tools/checkstyle/api/TokenTypes.html#RPAREN">RPAREN</a>
</tr>
</table>
<h4>Examples</h4>
<p class="body">
To configure the check:
</p>
<pre class="body">
&lt;module name=&quot;TypecastParenPad&quot;/&gt;
</pre>
<p class="body">
To configure the check to require spaces:
</p>
<pre class="body">
&lt;module name=&quot;TypecastParenPad&quot;&gt;
&lt;property name=&quot;option&quot; value=&quot;space&quot;/&gt;
&lt;/module&gt;
</pre>
<h4>Package</h4>
<p class="body">
com.puppycrawl.tools.checkstyle.checks.whitespace
</p>
<h4>Parent Module</h4>
<p class="body">
<a href="config.html#treewalker">TreeWalker</a>
</p>
<a name="TabCharacter"></a> <h2>TabCharacter</h2> <h4>Description</h4>
<p class="body">

View File

@ -73,6 +73,9 @@
not exceed a certain length (module AnonInnerLength,
request 715709, contributed by Rob Worth).</li>
<li class="body">Added TypecastParenPadCheck to check the padding of
typecasts (bug 750348).</li>
</ul>
<p class="body">

View File

@ -104,6 +104,7 @@
<module name="NoWhitespaceBefore"/>
<module name="OperatorWrap"/>
<module name="ParenPad"/>
<module name="TypecastParenPad"/>
<module name="TabCharacter"/>
<module name="WhitespaceAfter"/>
<module name="WhitespaceAround"/>

View File

@ -0,0 +1,91 @@
////////////////////////////////////////////////////////////////////////////////
// checkstyle: Checks Java source code for adherence to a set of rules.
// Copyright (C) 2001-2002 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.whitespace;
import com.puppycrawl.tools.checkstyle.api.DetailAST;
import com.puppycrawl.tools.checkstyle.api.Utils;
import com.puppycrawl.tools.checkstyle.checks.AbstractOptionCheck;
/**
* <p>Abstract class for checking the padding of parentheses. That is whether a
* space is required after a left parenthesis and before a right parenthesis,
* or such spaces are forbidden.
* </p>
* @author Oliver Burn
* @version 1.0
*/
abstract class AbstractParenPadCheck
extends AbstractOptionCheck
{
/**
* Sets the paren pad otion to nospace.
*/
AbstractParenPadCheck()
{
super(PadOption.NOSPACE);
}
/**
* Process a token representing a left parentheses.
* @param aAST the token representing a left parentheses
*/
protected void processLeft(DetailAST aAST)
{
final String line = getLines()[aAST.getLineNo() - 1];
final int after = aAST.getColumnNo() + 1;
if (after < line.length()) {
if ((PadOption.NOSPACE == getAbstractOption())
&& (Character.isWhitespace(line.charAt(after))))
{
log(aAST.getLineNo(), after, "ws.followed", "(");
}
else if ((PadOption.SPACE == getAbstractOption())
&& !Character.isWhitespace(line.charAt(after))
&& (line.charAt(after) != ')'))
{
log(aAST.getLineNo(), after, "ws.notFollowed", "(");
}
}
}
/**
* Process a token representing a right parentheses.
* @param aAST the token representing a right parentheses
*/
protected void processRight(DetailAST aAST)
{
final String line = getLines()[aAST.getLineNo() - 1];
final int before = aAST.getColumnNo() - 1;
if (before >= 0) {
if ((PadOption.NOSPACE == getAbstractOption())
&& Character.isWhitespace(line.charAt(before))
&& !Utils.whitespaceBefore(before, line))
{
log(aAST.getLineNo(), before, "ws.preceeded", ")");
}
else if ((PadOption.SPACE == getAbstractOption())
&& !Character.isWhitespace(line.charAt(before))
&& (line.charAt(before) != '('))
{
log(aAST.getLineNo(), aAST.getColumnNo(),
"ws.notPreceeded", ")");
}
}
}
}

View File

@ -21,8 +21,6 @@ package com.puppycrawl.tools.checkstyle.checks.whitespace;
import com.puppycrawl.tools.checkstyle.api.DetailAST;
import com.puppycrawl.tools.checkstyle.api.TokenTypes;
import com.puppycrawl.tools.checkstyle.api.Utils;
import com.puppycrawl.tools.checkstyle.checks.AbstractOptionCheck;
/**
* <p>Checks the padding of parentheses; that is whether a space is required
@ -65,16 +63,8 @@ import com.puppycrawl.tools.checkstyle.checks.AbstractOptionCheck;
* @version 1.0
*/
public class ParenPadCheck
extends AbstractOptionCheck
extends AbstractParenPadCheck
{
/**
* Sets the paren pad otion to nospace.
*/
public ParenPadCheck()
{
super(PadOption.NOSPACE);
}
/** @see com.puppycrawl.tools.checkstyle.api.Check */
public int[] getDefaultTokens()
{
@ -97,68 +87,28 @@ public class ParenPadCheck
else if ((aAST.getParent() == null)
|| (aAST.getParent().getType() != TokenTypes.TYPECAST))
{
processRight(aAST);
}
}
/**
* Process a token representing a left parentheses.
* @param aAST the token representing a left parentheses
*/
private void processLeft(DetailAST aAST)
{
final String line = getLines()[aAST.getLineNo() - 1];
final int after = aAST.getColumnNo() + 1;
if (after < line.length()) {
if ((PadOption.NOSPACE == getAbstractOption())
&& (Character.isWhitespace(line.charAt(after))))
{
log(aAST.getLineNo(), after, "ws.followed", "(");
}
else if ((PadOption.SPACE == getAbstractOption())
&& !Character.isWhitespace(line.charAt(after))
&& (line.charAt(after) != ')'))
{
log(aAST.getLineNo(), after, "ws.notFollowed", "(");
if (!isFollowsEmptyForIterator(aAST)) {
processRight(aAST);
}
}
}
/**
* Process a token representing a right parentheses.
* @param aAST the token representing a right parentheses
* @param aAST the token to check
* @return whether a token follows an empty for iterator
*/
private void processRight(DetailAST aAST)
private boolean isFollowsEmptyForIterator(DetailAST aAST)
{
final String line = getLines()[aAST.getLineNo() - 1];
final int before = aAST.getColumnNo() - 1;
if (before >= 0) {
boolean followsEmptyForIterator = false;
final DetailAST parent = aAST.getParent();
if ((parent != null)
&& (parent.getType() == TokenTypes.LITERAL_FOR))
{
final DetailAST forIterator =
parent.findFirstToken(TokenTypes.FOR_ITERATOR);
followsEmptyForIterator = (forIterator.getChildCount() == 0)
&& (aAST == forIterator.getNextSibling());
}
if (followsEmptyForIterator) {
return;
}
else if ((PadOption.NOSPACE == getAbstractOption())
&& Character.isWhitespace(line.charAt(before))
&& !Utils.whitespaceBefore(before, line))
{
log(aAST.getLineNo(), before, "ws.preceeded", ")");
}
else if ((PadOption.SPACE == getAbstractOption())
&& !Character.isWhitespace(line.charAt(before))
&& (line.charAt(before) != '('))
{
log(aAST.getLineNo(), aAST.getColumnNo(),
"ws.notPreceeded", ")");
}
boolean followsEmptyForIterator = false;
final DetailAST parent = aAST.getParent();
if ((parent != null)
&& (parent.getType() == TokenTypes.LITERAL_FOR))
{
final DetailAST forIterator =
parent.findFirstToken(TokenTypes.FOR_ITERATOR);
followsEmptyForIterator = (forIterator.getChildCount() == 0)
&& (aAST == forIterator.getNextSibling());
}
return followsEmptyForIterator;
}
}

View File

@ -0,0 +1,80 @@
////////////////////////////////////////////////////////////////////////////////
// checkstyle: Checks Java source code for adherence to a set of rules.
// Copyright (C) 2001-2002 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.whitespace;
import com.puppycrawl.tools.checkstyle.api.DetailAST;
import com.puppycrawl.tools.checkstyle.api.TokenTypes;
/**
* <p>Checks the padding of parentheses for typecasts. That is whether a space
* is required after a left parenthesis and before a right parenthesis, or such
* spaces are forbidden.
* <p>
* </p>
* The policy to verify is specified using the {@link PadOption} class and
* defaults to {@link PadOption#NOSPACE}.
* </p>
* <p>
* An example of how to configure the check is:
* </p>
* <pre>
* &lt;module name="TypecastParenPad"/&gt;
* </pre>
* <p>
* An example of how to configure the check to require spaces for the
* parentheses of constructor, method, and super constructor invocations is:
* </p>
* <pre>
* &lt;module name="TypecastParenPad"&gt;
* &lt;property name="option" value="space"/&gt;
* &lt;/module&gt;
* </pre>
* @author Oliver Burn
* @version 1.0
*/
public class TypecastParenPadCheck
extends AbstractParenPadCheck
{
/** @see com.puppycrawl.tools.checkstyle.api.Check */
public int[] getRequiredTokens()
{
return new int[] {TokenTypes.RPAREN, TokenTypes.TYPECAST};
}
/** @see com.puppycrawl.tools.checkstyle.api.Check */
public int[] getDefaultTokens()
{
return getRequiredTokens();
}
/** @see com.puppycrawl.tools.checkstyle.api.Check */
public void visitToken(DetailAST aAST)
{
// Strange logic in this method to guard against checking RPAREN tokens
// that are not associated with a TYPECAST token.
if (aAST.getType() == TokenTypes.TYPECAST) {
processLeft(aAST);
}
else if ((aAST.getParent() != null)
&& (aAST.getParent().getType() == TokenTypes.TYPECAST))
{
processRight(aAST);
}
}
}

View File

@ -86,7 +86,7 @@ class InputWhitespace
{
Object o = (Object) new Object(); // ok
o = (Object)o; // error
o = (Object) o; // ok
o = ( Object ) o; // ok
o = (Object)
o; // ok
}

View File

@ -65,6 +65,7 @@ import com.puppycrawl.tools.checkstyle.checks.whitespace.NoWhitespaceBeforeCheck
import com.puppycrawl.tools.checkstyle.checks.whitespace.OperatorWrapCheckTest;
import com.puppycrawl.tools.checkstyle.checks.whitespace.ParenPadCheckTest;
import com.puppycrawl.tools.checkstyle.checks.whitespace.TabCharacterCheckTest;
import com.puppycrawl.tools.checkstyle.checks.whitespace.TypecastParenPadCheckTest;
import com.puppycrawl.tools.checkstyle.checks.whitespace.WhitespaceAfterCheckTest;
import com.puppycrawl.tools.checkstyle.checks.whitespace.WhitespaceAroundTest;
import junit.framework.Test;
@ -148,6 +149,7 @@ public class AllTests {
suite.addTest(new TestSuite(TabCharacterCheckTest.class));
suite.addTest(new TestSuite(TodoCommentCheckTest.class));
suite.addTest(new TestSuite(TranslationCheckTest.class));
suite.addTest(new TestSuite(TypecastParenPadCheckTest.class));
suite.addTest(new TestSuite(LeftCurlyCheckTest.class));
suite.addTest(new TestSuite(TypeNameCheckTest.class));
suite.addTest(new TestSuite(UncommentedMainCheckTest.class));

View File

@ -0,0 +1,37 @@
package com.puppycrawl.tools.checkstyle.checks.whitespace;
import com.puppycrawl.tools.checkstyle.BaseCheckTestCase;
import com.puppycrawl.tools.checkstyle.DefaultConfiguration;
public class TypecastParenPadCheckTest
extends BaseCheckTestCase
{
public void testDefault()
throws Exception
{
final DefaultConfiguration checkConfig =
createCheckConfig(TypecastParenPadCheck.class);
final String[] expected = {
"89:14: '(' is followed by whitespace.",
"89:21: ')' is preceeded with whitespace.",
};
verify(checkConfig, getPath("InputWhitespace.java"), expected);
}
public void testSpace()
throws Exception
{
final DefaultConfiguration checkConfig =
createCheckConfig(TypecastParenPadCheck.class);
checkConfig.addAttribute("option", PadOption.SPACE.toString());
final String[] expected = {
"87:21: '(' is not followed by whitespace.",
"87:27: ')' is not preceeded with whitespace.",
"88:14: '(' is not followed by whitespace.",
"88:20: ')' is not preceeded with whitespace.",
"90:14: '(' is not followed by whitespace.",
"90:20: ')' is not preceeded with whitespace.",
};
verify(checkConfig, getPath("InputWhitespace.java"), expected);
}
}