RightCurly. Force line break before '}' in case SAME option. #250

This commit is contained in:
Max 2014-08-13 01:05:33 +04:00
parent a123763c92
commit 12a1aec080
6 changed files with 172 additions and 7 deletions

View File

@ -40,6 +40,11 @@ import com.puppycrawl.tools.checkstyle.checks.CheckUtils;
* {@link TokenTypes#CLASS_DEF CLASS_DEF},
* {@link TokenTypes#METHOD_DEF METHOD_DEF},
* {@link TokenTypes#CTOR_DEF CTOR_DEF}.
* {@link TokenTypes#LITERAL_FOR LITERAL_FOR}.
* {@link TokenTypes#LITERAL_WHILE LITERAL_WHILE}.
* {@link TokenTypes#LITERAL_DO LITERAL_DO}.
* {@link TokenTypes#STATIC_INIT STATIC_INIT}.
* {@link TokenTypes#INSTANCE_INIT INSTANCE_INIT}.
* </p>
* <p>
* An example of how to configure the check is:
@ -111,6 +116,11 @@ public class RightCurlyCheck extends AbstractOptionCheck<RightCurlyOption>
TokenTypes.CLASS_DEF,
TokenTypes.METHOD_DEF,
TokenTypes.CTOR_DEF,
TokenTypes.LITERAL_FOR,
TokenTypes.LITERAL_WHILE,
TokenTypes.LITERAL_DO,
TokenTypes.STATIC_INIT,
TokenTypes.INSTANCE_INIT,
};
}
@ -164,17 +174,27 @@ public class RightCurlyCheck extends AbstractOptionCheck<RightCurlyOption>
rcurly = lcurly.getLastChild();
break;
case TokenTypes.CLASS_DEF:
lcurly = aAST.getLastChild().getFirstChild();
rcurly = aAST.getLastChild().getLastChild();
final DetailAST child = aAST.getLastChild();
lcurly = child.getFirstChild();
rcurly = child.getLastChild();
nextToken = aAST;
break;
case TokenTypes.CTOR_DEF:
lcurly = aAST.getLastChild();
case TokenTypes.STATIC_INIT:
case TokenTypes.INSTANCE_INIT:
lcurly = aAST.findFirstToken(TokenTypes.SLIST);
rcurly = lcurly.getLastChild();
nextToken = aAST;
break;
case TokenTypes.METHOD_DEF:
lcurly = aAST.getLastChild();
case TokenTypes.LITERAL_FOR:
case TokenTypes.LITERAL_WHILE:
case TokenTypes.LITERAL_DO:
lcurly = aAST.findFirstToken(TokenTypes.SLIST);
//SLIST could be absent if method is abstract, and code like "while(true);"
if (lcurly == null) {
return;
}
rcurly = lcurly.getLastChild();
nextToken = aAST;
break;
@ -188,6 +208,10 @@ public class RightCurlyCheck extends AbstractOptionCheck<RightCurlyOption>
return;
}
if (getAbstractOption() == RightCurlyOption.SAME && !hasLineBreakBefore(rcurly)) {
log(rcurly, "line.break.before");
}
if (shouldCheckLastRcurly) {
if (rcurly.getLineNo() == nextToken.getLineNo()) {
log(rcurly, "line.alone", "}");
@ -251,4 +275,22 @@ public class RightCurlyCheck extends AbstractOptionCheck<RightCurlyOption>
}
return CheckUtils.getFirstNode(next);
}
/**
* Checks if right curly has line break before.
* @param aRightCurly
* Right curly token.
* @return
* True, if right curly has line break before.
*/
private boolean hasLineBreakBefore(DetailAST aRightCurly)
{
if (aRightCurly != null) {
final DetailAST previousToken = aRightCurly.getPreviousSibling();
if (previousToken != null && aRightCurly.getLineNo() == previousToken.getLineNo()) {
return false;
}
}
return true;
}
}

View File

@ -10,5 +10,4 @@ line.same=''{0}'' should be on the same line.
needBraces=''{0}'' construct must use '''{}'''s.
line.break.after='''{''' should have line break after.
line.break.before='''}''' should have line break before.

View File

@ -44,6 +44,8 @@ public class RightCurlyCheckTest extends BaseCheckTestSupport
"44:13: '}' should be on the same line.",
"93:27: '}' should be alone on a line.",
"93:27: '}' should be on a new line.",
"93:27: '}' should have line break before.",
"97:54: '}' should have line break before.",
};
verify(mCheckConfig, getPath("InputLeftCurlyOther.java"), expected);
}
@ -58,6 +60,8 @@ public class RightCurlyCheckTest extends BaseCheckTestSupport
"44:13: '}' should be on the same line.",
"93:27: '}' should be alone on a line.",
"93:27: '}' should be on a new line.",
"93:27: '}' should have line break before.",
"97:54: '}' should have line break before.",
};
verify(mCheckConfig, getPath("InputLeftCurlyOther.java"), expected);
}
@ -107,4 +111,40 @@ public class RightCurlyCheckTest extends BaseCheckTestSupport
};
verify(mCheckConfig, getPath("InputLeftCurlyOther.java"), expected);
}
@Test
public void testForceLineBreakBefore() throws Exception
{
mCheckConfig.addAttribute("option", RightCurlyOption.ALONE.toString());
mCheckConfig.addAttribute("tokens", "LITERAL_FOR,"
+ "LITERAL_WHILE, LITERAL_DO, STATIC_INIT, INSTANCE_INIT");
final String[] expected = {
"35:43: '}' should be alone on a line.",
"41:71: '}' should be alone on a line.",
"46:25: '}' should be alone on a line.",
};
verify(mCheckConfig, getPath("InputRightCurlyLineBreakBefore.java"), expected);
}
@Test
public void testForceLineBreakBefore2() throws Exception
{
final String[] expected = {
"24:33: '}' should have line break before.",
"32:44: '}' should have line break before.",
"32:63: '}' should have line break before.",
"50:48: '}' should have line break before.",
};
verify(mCheckConfig, getPath("InputRightCurlyLineBreakBefore.java"), expected);
}
@Test
public void testNPE() throws Exception
{
mCheckConfig.addAttribute("option", RightCurlyOption.ALONE.toString());
mCheckConfig.addAttribute("tokens", "CLASS_DEF, METHOD_DEF, CTOR_DEF, LITERAL_FOR, LITERAL_WHILE, LITERAL_DO, STATIC_INIT, INSTANCE_INIT");
final String[] expected = {
};
verify(mCheckConfig, getPath("InputRightCurlyEmptyAbstractMethod.java"), expected);
}
}

View File

@ -0,0 +1,8 @@
abstract class CharSequenceReader{
abstract void moveTo(double deltaX, double deltaY);
void foo() {
while (true);
}
}

View File

@ -0,0 +1,66 @@
package com.puppycrawl.tools.checkstyle;
import java.lang.annotation.ElementType;
import java.lang.annotation.Target;
import java.util.ArrayList;
import java.util.List;
class InputLeftCurlyOther
{
/** @see test method **/
int foo() throws InterruptedException
{
int x = 1;
int a = 2;
while (true)
{
try
{
if (x > 0)
{
break;
} else if (x < 0) {
;
} else { break; }
switch (a)
{
case 0:
break;
default:
break;
}
} catch (Exception e) { break; } finally { break; }
}
synchronized (this) { do { x = 2; } while (x == 2); }
synchronized (this) {
do {} while (x == 2);
}
for (int k = 0; k < 1; k++) { String innerBlockVariable = ""; }
for (int k = 0; k < 1; k++) {}
}
static { int x = 1; }
void method2()
{
if (flag) { System.err.println("foo"); }
}
}
class Absent_CustomFieldSerializer {
public static void serialize() {}
}
class Absent_CustomFieldSerializer
{
public Absent_CustomFieldSerializer() {}
}
class EmptyClass {}
interface EmptyInterface {}

View File

@ -303,7 +303,17 @@
<a
href="apidocs/com/puppycrawl/tools/checkstyle/api/TokenTypes.html#METHOD_DEF">METHOD_DEF</a>,
<a
href="apidocs/com/puppycrawl/tools/checkstyle/api/TokenTypes.html#CTOR_DEF">CTOR_DEF</a>.</td>
href="apidocs/com/puppycrawl/tools/checkstyle/api/TokenTypes.html#CTOR_DEF">CTOR_DEF</a>,
<a
href="apidocs/com/puppycrawl/tools/checkstyle/api/TokenTypes.html#LITERAL_FOR">LITERAL_FOR</a>,
<a
href="apidocs/com/puppycrawl/tools/checkstyle/api/TokenTypes.html#LITERAL_WHILE">LITERAL_WHILE</a>,
<a
href="apidocs/com/puppycrawl/tools/checkstyle/api/TokenTypes.html#LITERAL_DO">LITERAL_DO</a>,
<a
href="apidocs/com/puppycrawl/tools/checkstyle/api/TokenTypes.html#STATIC_INIT">STATIC_INIT</a>,
<a
href="apidocs/com/puppycrawl/tools/checkstyle/api/TokenTypes.html#INSTANCE_INIT">INSTANCE_INIT</a>.</td>
<td><a
href="apidocs/com/puppycrawl/tools/checkstyle/api/TokenTypes.html#LITERAL_TRY">LITERAL_TRY</a>,