added new check EmptyForInitializerPad and changed logic in NoWhiteSpaceBefore and ParenPad to fix bug #895072
This commit is contained in:
parent
0b2ea87e30
commit
da2328d0f1
|
|
@ -22,6 +22,9 @@
|
|||
<!--Left menu-->
|
||||
<td class="menu" valign="top">
|
||||
<ul>
|
||||
<li>
|
||||
<a href="#EmptyForInitializerPad">EmptyForInitializerPad</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#EmptyForIteratorPad">EmptyForIteratorPad</a>
|
||||
</li>
|
||||
|
|
@ -57,6 +60,59 @@
|
|||
<!--Content-->
|
||||
<td class="content" valign="top" align="left">
|
||||
|
||||
<a name="EmptyForInitializerPad"></a> <h2>EmptyForInitializerPad</h2> <h4>Description</h4>
|
||||
|
||||
<p class="body">
|
||||
Checks the padding of an empty for initializer; that is whether white
|
||||
space is required at an empty for initializer, or such white space is
|
||||
forbidden.
|
||||
No check occurs if there is a line wrap at the initializer, as in
|
||||
</p>
|
||||
<pre class="body">
|
||||
for (
|
||||
; i < j; i++, j--)
|
||||
</pre>
|
||||
<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 an empty for iterator</td>
|
||||
<td><a href="property_types.html#parenPad">pad policy</a></td>
|
||||
<td><span class="default">nospace</span></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<h4>Examples</h4>
|
||||
<p class="body">
|
||||
To configure the check:
|
||||
</p>
|
||||
<pre class="body">
|
||||
<module name="EmptyForInitializerPad"/>
|
||||
</pre>
|
||||
<p class="body">
|
||||
To configure the check to require white space at an empty for iterator:
|
||||
</p>
|
||||
<pre class="body">
|
||||
<module name="EmptyForInitializerPad">
|
||||
<property name="option" value="space"/>
|
||||
</module>
|
||||
</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="EmptyForIteratorPad"></a> <h2>EmptyForIteratorPad</h2> <h4>Description</h4>
|
||||
|
||||
<p class="body">
|
||||
|
|
@ -68,7 +124,7 @@
|
|||
<pre class="body">
|
||||
for (Iterator foo = very.long.line.iterator();
|
||||
foo.hasNext();
|
||||
)
|
||||
)
|
||||
</pre>
|
||||
<h4>Properties</h4>
|
||||
<table width="100%" border="1" cellpadding="5" class="body">
|
||||
|
|
|
|||
|
|
@ -120,10 +120,13 @@
|
|||
(request 885993).</li>
|
||||
|
||||
<li class="body">Added check to forbid endline
|
||||
comments. (module TrailingComment, reuest 744970)</li>
|
||||
comments. (module TrailingComment, request 744970)</li>
|
||||
|
||||
<li class="body">Added applyTo(Public|Protected|Package|Private)
|
||||
properties to check MemberName(request 695935)</li>
|
||||
properties to check MemberName. (request 695935)</li>
|
||||
|
||||
<li class="body">Added check to verify padding in empty for loop initializers.
|
||||
(module EmptyForInitializerPad, part of fix for bug 895072)</li>
|
||||
|
||||
</ul>
|
||||
|
||||
|
|
@ -161,6 +164,10 @@
|
|||
<li class="body">Cast causes MagicNumberCheck error.
|
||||
(bug 890706)</li>
|
||||
|
||||
<li class="body">Conflict between ParenPad and
|
||||
NoWhiteSpaceBefore when code uses empty for loop initializers. (bug 895072)
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
<p class="body">
|
||||
|
|
@ -170,6 +177,16 @@
|
|||
<li class="body">Removed ignoreLines property of
|
||||
RegexpHeader check. To make some line optional use
|
||||
"^.*$" regexp for this line.</li>
|
||||
|
||||
<li class="body">Fixing bug 895072 required changing the logic of
|
||||
the NoWhiteSpaceBefore and ParenPad checks.
|
||||
When a for loop has an empty initializer
|
||||
(like <span class="code">for (; i < j; i++)</span>)
|
||||
both checks will not check whitespace between the opening parenthesis
|
||||
and the first semicolon any more.
|
||||
To enforce your coding rules for such code, you have to use
|
||||
the EmptyForInitializerPad check (not available yet).</li>
|
||||
|
||||
</ul>
|
||||
|
||||
<a name="release3_3"></a>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,94 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
// checkstyle: Checks Java source code for adherence to a set of rules.
|
||||
// Copyright (C) 2001-2004 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;
|
||||
import com.puppycrawl.tools.checkstyle.api.Utils;
|
||||
import com.puppycrawl.tools.checkstyle.checks.AbstractOptionCheck;
|
||||
import com.puppycrawl.tools.checkstyle.checks.AbstractOption;
|
||||
|
||||
/**
|
||||
* <p>Checks the padding of an empty for initializer; that is whether a
|
||||
* space is required at an empty for initializer, or such spaces are
|
||||
* forbidden. No check occurs if there is a line wrap at the initializer, as in
|
||||
* </p>
|
||||
* <pre class="body">
|
||||
for (
|
||||
; i < j; i++, j--)
|
||||
</pre>
|
||||
* <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>
|
||||
* <module name="EmptyForInitializerPad"/>
|
||||
* </pre>
|
||||
* <p>
|
||||
* @author lkuehne
|
||||
* @version 1.0
|
||||
*/
|
||||
public class EmptyForInitializerPadCheck
|
||||
extends AbstractOptionCheck
|
||||
{
|
||||
/**
|
||||
* Sets the paren pad otion to nospace.
|
||||
*/
|
||||
public EmptyForInitializerPadCheck()
|
||||
{
|
||||
super(PadOption.NOSPACE);
|
||||
}
|
||||
|
||||
/** @see com.puppycrawl.tools.checkstyle.api.Check */
|
||||
public int[] getDefaultTokens()
|
||||
{
|
||||
return new int[] {TokenTypes.FOR_INIT,
|
||||
};
|
||||
}
|
||||
|
||||
/** @see com.puppycrawl.tools.checkstyle.api.Check */
|
||||
public void visitToken(DetailAST aAST)
|
||||
{
|
||||
if (aAST.getChildCount() == 0) {
|
||||
//empty for initializer. test pad before semi.
|
||||
final DetailAST semi = (DetailAST) aAST.getNextSibling();
|
||||
final int semiLineIdx = semi.getLineNo() - 1;
|
||||
final String line = getLines()[semiLineIdx];
|
||||
final int before = semi.getColumnNo() - 1;
|
||||
//don't check if semi at beginning of line
|
||||
if (!Utils.whitespaceBefore(before, line)) {
|
||||
final AbstractOption abstractOption = getAbstractOption();
|
||||
if ((PadOption.NOSPACE == abstractOption)
|
||||
&& (Character.isWhitespace(line.charAt(before))))
|
||||
{
|
||||
log(semi.getLineNo(), before, "ws.preceded", ";");
|
||||
}
|
||||
else if ((PadOption.SPACE == abstractOption)
|
||||
&& !Character.isWhitespace(line.charAt(before)))
|
||||
{
|
||||
log(semi.getLineNo(), before, "ws.notPreceded", ";");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -92,6 +92,18 @@ public class NoWhitespaceBeforeCheck
|
|||
final int before = aAST.getColumnNo() - 1;
|
||||
|
||||
if ((before < 0) || Character.isWhitespace(line.charAt(before))) {
|
||||
|
||||
// empty FOR initializer?
|
||||
if (aAST.getType() == TokenTypes.SEMI) {
|
||||
final DetailAST sibling = aAST.getPreviousSibling();
|
||||
if ((sibling != null)
|
||||
&& (sibling.getType() == TokenTypes.FOR_INIT)
|
||||
&& (sibling.getChildCount() == 0))
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
boolean flag = !mAllowLineBreaks;
|
||||
// verify all characters before '.' are whitespace
|
||||
for (int i = 0; !flag && i < before; i++) {
|
||||
|
|
|
|||
|
|
@ -82,7 +82,9 @@ public class ParenPadCheck
|
|||
// Strange logic in this method to guard against checking RPAREN tokens
|
||||
// that are associated with a TYPECAST token.
|
||||
if (aAST.getType() != TokenTypes.RPAREN) {
|
||||
processLeft(aAST);
|
||||
if (!isPreceedsEmptyForInit(aAST)) {
|
||||
processLeft(aAST);
|
||||
}
|
||||
}
|
||||
else if ((aAST.getParent() == null)
|
||||
|| (aAST.getParent().getType() != TokenTypes.TYPECAST))
|
||||
|
|
@ -111,4 +113,23 @@ public class ParenPadCheck
|
|||
}
|
||||
return followsEmptyForIterator;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param aAST the token to check
|
||||
* @return whether a token preceeds an empty for initializer
|
||||
*/
|
||||
private boolean isPreceedsEmptyForInit(DetailAST aAST)
|
||||
{
|
||||
boolean preceedsEmptyForInintializer = false;
|
||||
final DetailAST parent = aAST.getParent();
|
||||
if ((parent != null)
|
||||
&& (parent.getType() == TokenTypes.LITERAL_FOR))
|
||||
{
|
||||
final DetailAST forIterator =
|
||||
parent.findFirstToken(TokenTypes.FOR_INIT);
|
||||
preceedsEmptyForInintializer = (forIterator.getChildCount() == 0)
|
||||
&& (aAST == forIterator.getPreviousSibling());
|
||||
}
|
||||
return preceedsEmptyForInintializer;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,4 +34,21 @@ class InputForWhitespace
|
|||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
void method2()
|
||||
{
|
||||
for ( int i = 0; i < 1; i++ ) {
|
||||
}
|
||||
|
||||
for ( int i = 0; i < 1; ) {
|
||||
i++;
|
||||
}
|
||||
|
||||
int i = 0;
|
||||
for ( ; i < 1; i++ ) {
|
||||
}
|
||||
|
||||
for (; i < 2; i++ ) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -208,3 +208,26 @@ interface IFoo
|
|||
void foo() ;
|
||||
// ^ whitespace
|
||||
}
|
||||
|
||||
/**
|
||||
* Avoid Whitespace errors in for loop.
|
||||
* @author lkuehne
|
||||
* @version 1.0
|
||||
*/
|
||||
class SpecialCasesInForLoop
|
||||
{
|
||||
void forIterator()
|
||||
{
|
||||
// avoid conflict between WhiteSpaceAfter ';' and ParenPad(nospace)
|
||||
for (int i = 0; i++ < 5;) {
|
||||
// ^ no whitespace
|
||||
}
|
||||
|
||||
// bug 895072
|
||||
// avoid confilct between ParenPad(space) and NoWhiteSpace before ';'
|
||||
int i = 0;
|
||||
for ( ; i < 5; i++ ) {
|
||||
// ^ whitespace
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ public class AllTests {
|
|||
TestSuite suite =
|
||||
new TestSuite("Test for com.puppycrawl.tools.checkstyle.checks.whitespace");
|
||||
|
||||
suite.addTest(new TestSuite(EmptyForInitializerPadCheckTest.class));
|
||||
suite.addTest(new TestSuite(EmptyForIteratorPadCheckTest.class));
|
||||
suite.addTest(new TestSuite(MethodParamPadCheckTest.class));
|
||||
suite.addTest(new TestSuite(NoWhitespaceAfterCheckTest.class));
|
||||
|
|
|
|||
|
|
@ -0,0 +1,32 @@
|
|||
package com.puppycrawl.tools.checkstyle.checks.whitespace;
|
||||
|
||||
import com.puppycrawl.tools.checkstyle.BaseCheckTestCase;
|
||||
import com.puppycrawl.tools.checkstyle.DefaultConfiguration;
|
||||
|
||||
public class EmptyForInitializerPadCheckTest
|
||||
extends BaseCheckTestCase
|
||||
{
|
||||
private DefaultConfiguration mCheckConfig;
|
||||
|
||||
public void setUp()
|
||||
{
|
||||
mCheckConfig = createCheckConfig(EmptyForInitializerPadCheck.class);
|
||||
}
|
||||
|
||||
public void testDefault() throws Exception
|
||||
{
|
||||
final String[] expected = {
|
||||
"48:14: ';' is preceded with whitespace.",
|
||||
};
|
||||
verify(mCheckConfig, getPath("InputForWhitespace.java"), expected);
|
||||
}
|
||||
|
||||
public void testSpaceOption() throws Exception
|
||||
{
|
||||
mCheckConfig.addAttribute("option", PadOption.SPACE.toString());
|
||||
final String[] expected = {
|
||||
"51:13: ';' is not preceded with whitespace.",
|
||||
};
|
||||
verify(mCheckConfig, getPath("InputForWhitespace.java"), expected);
|
||||
}
|
||||
}
|
||||
|
|
@ -17,6 +17,7 @@ public class EmptyForIteratorPadCheckTest
|
|||
{
|
||||
final String[] expected = {
|
||||
"27:31: ';' is followed by whitespace.",
|
||||
"43:32: ';' is followed by whitespace.",
|
||||
};
|
||||
verify(mCheckConfig, getPath("InputForWhitespace.java"), expected);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ public class ParenPadCheckTest
|
|||
"58:36: ')' is preceded with whitespace.",
|
||||
"74:13: '(' is followed by whitespace.",
|
||||
"74:18: ')' is preceded with whitespace.",
|
||||
"229:27: ')' is preceded with whitespace.",
|
||||
};
|
||||
verify(checkConfig, getPath("InputWhitespace.java"), expected);
|
||||
}
|
||||
|
|
@ -49,6 +50,7 @@ public class ParenPadCheckTest
|
|||
"165:10: ')' is not preceded with whitespace.",
|
||||
"178:14: '(' is not followed by whitespace.",
|
||||
"178:36: ')' is not preceded with whitespace.",
|
||||
"222:14: '(' is not followed by whitespace.",
|
||||
};
|
||||
verify(checkConfig, getPath("InputWhitespace.java"), expected);
|
||||
}
|
||||
|
|
@ -61,6 +63,11 @@ public class ParenPadCheckTest
|
|||
final String[] expected = {
|
||||
"17:34: ')' is preceded with whitespace.",
|
||||
"20:35: ')' is preceded with whitespace.",
|
||||
"40:14: '(' is followed by whitespace.",
|
||||
"40:36: ')' is preceded with whitespace.",
|
||||
"43:14: '(' is followed by whitespace.",
|
||||
"48:27: ')' is preceded with whitespace.",
|
||||
"51:26: ')' is preceded with whitespace.",
|
||||
};
|
||||
verify(checkConfig, getPath("InputForWhitespace.java"), expected);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue