diff --git a/src/main/java/com/puppycrawl/tools/checkstyle/checks/blocks/RightCurlyCheck.java b/src/main/java/com/puppycrawl/tools/checkstyle/checks/blocks/RightCurlyCheck.java
index e56dc5d35..fdb0411c7 100644
--- a/src/main/java/com/puppycrawl/tools/checkstyle/checks/blocks/RightCurlyCheck.java
+++ b/src/main/java/com/puppycrawl/tools/checkstyle/checks/blocks/RightCurlyCheck.java
@@ -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}.
*
*
* An example of how to configure the check is:
@@ -111,6 +116,11 @@ public class RightCurlyCheck extends AbstractOptionCheck
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
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
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
}
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;
+ }
}
diff --git a/src/main/resources/com/puppycrawl/tools/checkstyle/checks/blocks/messages.properties b/src/main/resources/com/puppycrawl/tools/checkstyle/checks/blocks/messages.properties
index 42b68e3af..0abbcfbf5 100644
--- a/src/main/resources/com/puppycrawl/tools/checkstyle/checks/blocks/messages.properties
+++ b/src/main/resources/com/puppycrawl/tools/checkstyle/checks/blocks/messages.properties
@@ -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.
diff --git a/src/test/java/com/puppycrawl/tools/checkstyle/checks/blocks/RightCurlyCheckTest.java b/src/test/java/com/puppycrawl/tools/checkstyle/checks/blocks/RightCurlyCheckTest.java
index 5da950bbc..89c448cd3 100644
--- a/src/test/java/com/puppycrawl/tools/checkstyle/checks/blocks/RightCurlyCheckTest.java
+++ b/src/test/java/com/puppycrawl/tools/checkstyle/checks/blocks/RightCurlyCheckTest.java
@@ -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);
+ }
}
diff --git a/src/test/resources/com/puppycrawl/tools/checkstyle/InputRightCurlyEmptyAbstractMethod.java b/src/test/resources/com/puppycrawl/tools/checkstyle/InputRightCurlyEmptyAbstractMethod.java
new file mode 100644
index 000000000..c581027b1
--- /dev/null
+++ b/src/test/resources/com/puppycrawl/tools/checkstyle/InputRightCurlyEmptyAbstractMethod.java
@@ -0,0 +1,8 @@
+abstract class CharSequenceReader{
+
+ abstract void moveTo(double deltaX, double deltaY);
+
+ void foo() {
+ while (true);
+ }
+}
\ No newline at end of file
diff --git a/src/test/resources/com/puppycrawl/tools/checkstyle/InputRightCurlyLineBreakBefore.java b/src/test/resources/com/puppycrawl/tools/checkstyle/InputRightCurlyLineBreakBefore.java
new file mode 100644
index 000000000..96858fce8
--- /dev/null
+++ b/src/test/resources/com/puppycrawl/tools/checkstyle/InputRightCurlyLineBreakBefore.java
@@ -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 {}
\ No newline at end of file
diff --git a/src/xdocs/config_blocks.xml b/src/xdocs/config_blocks.xml
index dc65783b2..6b14b6512 100644
--- a/src/xdocs/config_blocks.xml
+++ b/src/xdocs/config_blocks.xml
@@ -303,7 +303,17 @@
METHOD_DEF,
CTOR_DEF.
+ href="apidocs/com/puppycrawl/tools/checkstyle/api/TokenTypes.html#CTOR_DEF">CTOR_DEF,
+ LITERAL_FOR,
+ LITERAL_WHILE,
+ LITERAL_DO,
+ STATIC_INIT,
+ INSTANCE_INIT.
| LITERAL_TRY,
|