Repository: checkstyle/checkstyle (Java)

Issue:
LITERAL_CASE token support in RightCurlyCheck
Currently [RightCurlyCheck](https://checkstyle.org/checks/blocks/rightcurly.html#RightCurly) accepts a less tokens than [LeftCurlyCheck](https://checkstyle.org/checks/blocks/leftcurly.html#LeftCurly) (19 tokens)
This issue aims to add support for `LITERAL_CASE` token in RightCurlyCheck 
this issue is a child issue for https://github.com/checkstyle/checkstyle/issues/3547

For LeftCurlyCheck:

```
PS D:\test> cat config.xml                                                   
<?xml version="1.0"?>
<!DOCTYPE module PUBLIC
          "-//Puppy Crawl//DTD Check Configuration 1.3//EN"
          "http://www.puppycrawl.com/dtds/configuration_1_3.dtd">

<module name="Checker">
    <property name="charset" value="UTF-8"/>

 <module name="TreeWalker">

      <module name="LeftCurly">
            <property name="tokens" value="LITERAL_CASE "/>
          <property name="option" value="eol"/>
        </module>
    </module>
</module>
PS D:\test> cat src/Test.java                                                
class Test{

    void test(){
        int x = 1;
        switch(x){
            case 1:
            {        // violation
                System.out.println("x is 1");
                break;
            }
            case 2:
            {     // violation
                System.out.println("x is 2");
                break;
            }
            default:
                System.out.println("x is neither 1 nor 2");
        }
    }
}
PS D:\test> java  -jar checkstyle-10.13.0-all.jar -c config.xml src/Test.java
Starting audit...
[ERROR] D:\test\src\Test.java:7:13: '{' at column 13 should be on the previous line. [LeftCurly]
[ERROR] D:\test\src\Test.java:12:13: '{' at column 13 should be on the previous line. [LeftCurly]
Audit done.
Checkstyle ends with 2 errors.
```
for RightCurlyCheck:

```
PS D:\test> cat config.xml                                                   
<?xml version="1.0"?>
<!DOCTYPE module PUBLIC
          "-//Puppy Crawl//DTD Check Configuration 1.3//EN"
          "http://www.puppycrawl.com/dtds/configuration_1_3.dtd">

<module name="Checker">
    <property name="charset" value="UTF-8"/>

 <module name="TreeWalker">

      <module name="RightCurly">
            <property name="tokens" value="LITERAL_CASE"/>
          <property name="option" value="alone"/>
        </module>
    </module>
</module>
PS D:\test> cat src/Test.java                                                
class Test{

    void test(){
        int x = 1;
        switch(x){
            case 1:
            {
                System.out.println("x is 1");
                break;
            } case 2:                       // expected violation '}' should be alone in the line
            {
                System.out.println("x is 2");
                break;
            } default:                        // expected violation '}' should be alone in the line
                System.out.println("x is neither 1 nor 2");
        }
    }
}
```
Expected:- Violation for the right curly brace for  `LITERAL_CASE `



Discussion: @mahfouz72 thanks for your report,  issue is approved.

Tests for this need to include:
 - Different inputs with all [RightCurlyOption](https://checkstyle.org/property_types.html#RightCurlyOption)s
 - switch statements, expressions
 - switch rules and block statements

I am on it
> switch statements, expressions

@nrmancuso but I found in the check code that the check is handling statements only not expressions so do you mean to add tests to show that it isn't getting checked?



> > switch statements, expressions
> 
> @nrmancuso but I found in the check code that the check is handling statements only not expressions so do you mean to add tests to show that it isn't getting checked?

@mahfouz72 i like to think about issues vs PRs (generally) like this: in issues, we talk about *behavior*, and in PRs, we talk about *code*. 

As far as behavior goes, I would expect braces for the `SLIST` of any `LITERAL_CASE` to be checked, regardless of where this token appears. 

If RightCurlyCheck doesn’t check the closing right curly brace of a switch expression, this sounds like a different (but valid) issue. 



Fix (patch):
diff --git a/config/checker-framework-suppressions/checker-nullness-optional-interning-suppressions.xml b/config/checker-framework-suppressions/checker-nullness-optional-interning-suppressions.xml
index 069d8d303b8..5604b4e3f15 100644
--- a/config/checker-framework-suppressions/checker-nullness-optional-interning-suppressions.xml
+++ b/config/checker-framework-suppressions/checker-nullness-optional-interning-suppressions.xml
@@ -1574,6 +1574,17 @@
     <lineContent>.orElse(Boolean.TRUE);</lineContent>
   </checkerFrameworkError>
 
+  <checkerFrameworkError unstable="false">
+    <fileName>src/main/java/com/puppycrawl/tools/checkstyle/checks/blocks/RightCurlyCheck.java</fileName>
+    <specifier>argument</specifier>
+    <message>incompatible argument for parameter lcurly of Details constructor.</message>
+    <lineContent>return new Details(lcurly.orElse(null), rcurly, nextToken.orElse(null), true);</lineContent>
+    <details>
+      found   : @Initialized @Nullable DetailAST
+      required: @Initialized @NonNull DetailAST
+    </details>
+  </checkerFrameworkError>
+
   <checkerFrameworkError unstable="false">
     <fileName>src/main/java/com/puppycrawl/tools/checkstyle/checks/blocks/RightCurlyCheck.java</fileName>
     <specifier>argument</specifier>
@@ -1585,6 +1596,17 @@
     </details>
   </checkerFrameworkError>
 
+  <checkerFrameworkError unstable="false">
+    <fileName>src/main/java/com/puppycrawl/tools/checkstyle/checks/blocks/RightCurlyCheck.java</fileName>
+    <specifier>argument</specifier>
+    <message>incompatible argument for parameter nextToken of Details constructor.</message>
+    <lineContent>return new Details(lcurly.orElse(null), rcurly, nextToken.orElse(null), true);</lineContent>
+    <details>
+      found   : @Initialized @Nullable DetailAST
+      required: @Initialized @NonNull DetailAST
+    </details>
+  </checkerFrameworkError>
+
   <checkerFrameworkError unstable="false">
     <fileName>src/main/java/com/puppycrawl/tools/checkstyle/checks/blocks/RightCurlyCheck.java</fileName>
     <specifier>argument</specifier>
@@ -1629,6 +1651,17 @@
     </details>
   </checkerFrameworkError>
 
+  <checkerFrameworkError unstable="false">
+    <fileName>src/main/java/com/puppycrawl/tools/checkstyle/checks/blocks/RightCurlyCheck.java</fileName>
+    <specifier>argument</specifier>
+    <message>incompatible argument for parameter rcurly of Details constructor.</message>
+    <lineContent>return new Details(lcurly.orElse(null), rcurly, nextToken.orElse(null), true);</lineContent>
+    <details>
+      found   : @Initialized @Nullable DetailAST
+      required: @Initialized @NonNull DetailAST
+    </details>
+  </checkerFrameworkError>
+
   <checkerFrameworkError unstable="false">
     <fileName>src/main/java/com/puppycrawl/tools/checkstyle/checks/blocks/RightCurlyCheck.java</fileName>
     <specifier>return</specifier>
diff --git a/config/checkstyle-checks.xml b/config/checkstyle-checks.xml
index 8c6fceefe4a..90ebb258732 100644
--- a/config/checkstyle-checks.xml
+++ b/config/checkstyle-checks.xml
@@ -330,6 +330,7 @@
       <property name="tokens" value="ENUM_DEF"/>
       <property name="tokens" value="RECORD_DEF"/>
       <property name="tokens" value="COMPACT_CTOR_DEF"/>
+      <property name="tokens" value="LITERAL_CASE"/>
       <property name="option" value="alone"/>
     </module>
     <module name="RightCurly">
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 ea0c05057b0..b26f545014c 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
@@ -21,6 +21,7 @@
 
 import java.util.Arrays;
 import java.util.Locale;
+import java.util.Optional;
 
 import com.puppycrawl.tools.checkstyle.StatelessCheck;
 import com.puppycrawl.tools.checkstyle.api.AbstractCheck;
@@ -32,8 +33,8 @@
 /**
  * <p>
  * Checks the placement of right curly braces (<code>'}'</code>) for code blocks. This check
- * supports if-else, try-catch-finally blocks, switch statements, while-loops, for-loops,
- * method definitions, class definitions, constructor definitions,
+ * supports if-else, try-catch-finally blocks, switch statements, switch cases, while-loops,
+ *  for-loops, method definitions, class definitions, constructor definitions,
  * instance, static initialization blocks, annotation definitions and enum definitions.
  * For right curly brace of expression blocks of arrays, lambdas and class instances
  * please follow issue
@@ -155,6 +156,7 @@ public int[] getAcceptableTokens() {
             TokenTypes.RECORD_DEF,
             TokenTypes.COMPACT_CTOR_DEF,
             TokenTypes.LITERAL_SWITCH,
+            TokenTypes.LITERAL_CASE,
         };
     }
 
@@ -432,6 +434,9 @@ private static Details getDetails(DetailAST ast) {
                 case TokenTypes.LITERAL_SWITCH:
                     details = getDetailsForSwitch(ast);
                     break;
+                case TokenTypes.LITERAL_CASE:
+                    details = getDetailsForCase(ast);
+                    break;
                 default:
                     details = getDetailsForOthers(ast);
                     break;
@@ -460,6 +465,38 @@ private static Details getDetailsForSwitch(DetailAST switchNode) {
             return new Details(lcurly, rcurly, nextToken, true);
         }
 
+        /**
+         * Collects details about case statements.
+         *
+         * @param caseNode case statement to gather details about
+         * @return new Details about given case statement
+         */
+        private static Details getDetailsForCase(DetailAST caseNode) {
+            final DetailAST caseParent = caseNode.getParent();
+            final int parentType = caseParent.getType();
+            final Optional<DetailAST> lcurly;
+            final DetailAST statementList;
+
+            if (parentType == TokenTypes.SWITCH_RULE) {
+                statementList = caseParent.findFirstToken(TokenTypes.SLIST);
+                lcurly = Optional.ofNullable(statementList);
+            }
+            else {
+                statementList = caseNode.getNextSibling();
+                lcurly = Optional.ofNullable(statementList)
+                         .map(DetailAST::getFirstChild)
+                         .filter(node -> node.getType() == TokenTypes.SLIST);
+            }
+            final DetailAST rcurly = lcurly.map(DetailAST::getLastChild)
+                    .filter(child -> !isSwitchExpression(caseParent))
+                    .orElse(null);
+            final Optional<DetailAST> nextToken =
+                    Optional.ofNullable(lcurly.map(DetailAST::getNextSibling)
+                    .orElseGet(() -> getNextToken(caseParent)));
+
+            return new Details(lcurly.orElse(null), rcurly, nextToken.orElse(null), true);
+        }
+
         /**
          * Check whether switch is expression or not.
          *
diff --git a/src/main/resources/com/puppycrawl/tools/checkstyle/meta/checks/blocks/RightCurlyCheck.xml b/src/main/resources/com/puppycrawl/tools/checkstyle/meta/checks/blocks/RightCurlyCheck.xml
index e28034710f2..274b71e2c50 100644
--- a/src/main/resources/com/puppycrawl/tools/checkstyle/meta/checks/blocks/RightCurlyCheck.xml
+++ b/src/main/resources/com/puppycrawl/tools/checkstyle/meta/checks/blocks/RightCurlyCheck.xml
@@ -6,8 +6,8 @@
              parent="com.puppycrawl.tools.checkstyle.TreeWalker">
          <description>&lt;p&gt;
  Checks the placement of right curly braces (&lt;code&gt;'}'&lt;/code&gt;) for code blocks. This check
- supports if-else, try-catch-finally blocks, switch statements, while-loops, for-loops,
- method definitions, class definitions, constructor definitions,
+ supports if-else, try-catch-finally blocks, switch statements, switch cases, while-loops,
+  for-loops, method definitions, class definitions, constructor definitions,
  instance, static initialization blocks, annotation definitions and enum definitions.
  For right curly brace of expression blocks of arrays, lambdas and class instances
  please follow issue
diff --git a/src/main/resources/google_checks.xml b/src/main/resources/google_checks.xml
index bc47e7e7767..afdbfe5d56b 100644
--- a/src/main/resources/google_checks.xml
+++ b/src/main/resources/google_checks.xml
@@ -96,7 +96,7 @@
       <property name="tokens"
                value="CLASS_DEF, METHOD_DEF, CTOR_DEF, LITERAL_FOR, LITERAL_WHILE, STATIC_INIT,
                     INSTANCE_INIT, ANNOTATION_DEF, ENUM_DEF, INTERFACE_DEF, RECORD_DEF,
-                    COMPACT_CTOR_DEF, LITERAL_SWITCH"/>
+                    COMPACT_CTOR_DEF, LITERAL_SWITCH, LITERAL_CASE"/>
     </module>
     <module name="SuppressionXpathSingleFilter">
       <!-- suppresion is required till https://github.com/checkstyle/checkstyle/issues/7541 -->
diff --git a/src/xdocs-examples/java/com/puppycrawl/tools/checkstyle/checks/blocks/RightCurlyCheckExamplesTest.java b/src/xdocs-examples/java/com/puppycrawl/tools/checkstyle/checks/blocks/RightCurlyCheckExamplesTest.java
index 732751ef204..8499aba95a3 100644
--- a/src/xdocs-examples/java/com/puppycrawl/tools/checkstyle/checks/blocks/RightCurlyCheckExamplesTest.java
+++ b/src/xdocs-examples/java/com/puppycrawl/tools/checkstyle/checks/blocks/RightCurlyCheckExamplesTest.java
@@ -56,7 +56,8 @@ public void testExample2() throws Exception {
     @Test
     public void testExample3() throws Exception {
         final String[] expected = {
-            "35:16: " + getCheckMessage(MSG_KEY_LINE_ALONE, "}", "16"),
+            "24:22: " + getCheckMessage(MSG_KEY_LINE_ALONE, "}", "22"),
+            "38:16: " + getCheckMessage(MSG_KEY_LINE_ALONE, "}", "16"),
         };
 
         verifyWithInlineConfigParser(getPath("Example3.java"), expected);
@@ -74,7 +75,7 @@ public void testExample4() throws Exception {
     @Test
     public void testExample5() throws Exception {
         final String[] expected = {
-            "41:16: " + getCheckMessage(MSG_KEY_LINE_ALONE, "}", "16"),
+            "44:16: " + getCheckMessage(MSG_KEY_LINE_ALONE, "}", "16"),
         };
 
         verifyWithInlineConfigParser(getPath("Example5.java"), expected);
diff --git a/src/xdocs-examples/resources/com/puppycrawl/tools/checkstyle/checks/blocks/rightcurly/Example3.java b/src/xdocs-examples/resources/com/puppycrawl/tools/checkstyle/checks/blocks/rightcurly/Example3.java
index 3b359e9f5c0..53de6d85ae6 100644
--- a/src/xdocs-examples/resources/com/puppycrawl/tools/checkstyle/checks/blocks/rightcurly/Example3.java
+++ b/src/xdocs-examples/resources/com/puppycrawl/tools/checkstyle/checks/blocks/rightcurly/Example3.java
@@ -3,7 +3,7 @@
   <module name="TreeWalker">
     <module name="RightCurly">
       <property name="option" value="alone"/>
-      <property name="tokens" value="LITERAL_SWITCH"/>
+      <property name="tokens" value="LITERAL_SWITCH, LITERAL_CASE"/>
     </module>
   </module>
 </module>
@@ -16,10 +16,13 @@ class Example3 {
 
   public void method0() {
     int mode = 0;
+    int x;
     switch (mode) {
       case 1:
-        int x = 1;
+        int y = 1;
         break;
+      case 2: {x = 1;}   // violation '}' at column 22 should be alone on a line'
+      case 3: int z = 0; {break;} // ok, the braces is not a first child of case
       default:
         x = 0;
     } // ok, RightCurly is alone
@@ -35,6 +38,5 @@ public void method01() {
         x = 0; }
     // violation above, 'should be alone on a line.'
   }
-
 }
 // xdoc section -- end
diff --git a/src/xdocs-examples/resources/com/puppycrawl/tools/checkstyle/checks/blocks/rightcurly/Example5.java b/src/xdocs-examples/resources/com/puppycrawl/tools/checkstyle/checks/blocks/rightcurly/Example5.java
index 730135fdb94..38e3b2a79d8 100644
--- a/src/xdocs-examples/resources/com/puppycrawl/tools/checkstyle/checks/blocks/rightcurly/Example5.java
+++ b/src/xdocs-examples/resources/com/puppycrawl/tools/checkstyle/checks/blocks/rightcurly/Example5.java
@@ -3,7 +3,7 @@
   <module name="TreeWalker">
     <module name="RightCurly">
       <property name="option" value="alone_or_singleline"/>
-      <property name="tokens" value="LITERAL_SWITCH"/>
+      <property name="tokens" value="LITERAL_SWITCH, LITERAL_CASE"/>
     </module>
   </module>
 </module>
@@ -16,10 +16,13 @@ class Example5 {
 
   public void method0() {
     int mode = 0;
+    int x;
     switch (mode) {
       case 1:
-        int x = 1;
+        int y = 1;
         break;
+      case 2: {x = 1;}   // ok, RightCurly is in single line
+      case 3: int z = 0; {break;} // ok, the braces is not a first child of case
       default:
         x = 0;
     }
diff --git a/src/xdocs/checks/blocks/rightcurly.xml b/src/xdocs/checks/blocks/rightcurly.xml
index bc46c4ee522..0336c319cc7 100644
--- a/src/xdocs/checks/blocks/rightcurly.xml
+++ b/src/xdocs/checks/blocks/rightcurly.xml
@@ -11,7 +11,7 @@
       <subsection name="Description" id="Description">
         <p>
           Checks the placement of right curly braces (<code>'}'</code>) for code blocks.
-          This check supports if-else, try-catch-finally blocks, switch statements,
+          This check supports if-else, try-catch-finally blocks, switch statements, switch cases,
           while-loops, for-loops, method definitions, class definitions, constructor definitions,
           instance, static initialization blocks, annotation definitions and enum definitions.
           For right curly brace of expression blocks of arrays, lambdas and class instances
@@ -81,6 +81,8 @@
                     COMPACT_CTOR_DEF</a>
                 , <a href="../../apidocs/com/puppycrawl/tools/checkstyle/api/TokenTypes.html#LITERAL_SWITCH">
                     LITERAL_SWITCH</a>
+                , <a href="../../apidocs/com/puppycrawl/tools/checkstyle/api/TokenTypes.html#LITERAL_CASE">
+                    LITERAL_CASE</a>
                   .
               </td>
               <td>
@@ -220,14 +222,14 @@ public class Example2 {
           To configure the check with policy <code>alone</code> for
           <a href="https://docs.oracle.com/javase/tutorial/java/nutsandbolts/switch.html">
           Switch</a>
-          Statements:
+          Statements and Switch Cases:
         </p>
         <source>
 &lt;module name=&quot;Checker&quot;&gt;
   &lt;module name=&quot;TreeWalker&quot;&gt;
     &lt;module name=&quot;RightCurly&quot;&gt;
       &lt;property name=&quot;option&quot; value=&quot;alone&quot;/&gt;
-      &lt;property name=&quot;tokens&quot; value=&quot;LITERAL_SWITCH&quot;/&gt;
+      &lt;property name=&quot;tokens&quot; value=&quot;LITERAL_SWITCH, LITERAL_CASE&quot;/&gt;
     &lt;/module&gt;
   &lt;/module&gt;
 &lt;/module&gt;
@@ -238,10 +240,13 @@ class Example3 {
 
   public void method0() {
     int mode = 0;
+    int x;
     switch (mode) {
       case 1:
-        int x = 1;
+        int y = 1;
         break;
+      case 2: {x = 1;}   // violation '}' at column 22 should be alone on a line'
+      case 3: int z = 0; {break;} // ok, the braces is not a first child of case
       default:
         x = 0;
     } // ok, RightCurly is alone
@@ -257,7 +262,6 @@ class Example3 {
         x = 0; }
     // violation above, 'should be alone on a line.'
   }
-
 }
         </source>
         <p id="Example4-config">
@@ -315,14 +319,14 @@ public class Example4 {
           To configure the check with policy <code>alone_or_singleline</code> for
           <a href="https://docs.oracle.com/javase/tutorial/java/nutsandbolts/switch.html">
           Switch</a>
-          Statements:
+          Statements and Switch Cases:
         </p>
         <source>
 &lt;module name=&quot;Checker&quot;&gt;
   &lt;module name=&quot;TreeWalker&quot;&gt;
     &lt;module name=&quot;RightCurly&quot;&gt;
       &lt;property name=&quot;option&quot; value=&quot;alone_or_singleline&quot;/&gt;
-      &lt;property name=&quot;tokens&quot; value=&quot;LITERAL_SWITCH&quot;/&gt;
+      &lt;property name=&quot;tokens&quot; value=&quot;LITERAL_SWITCH, LITERAL_CASE&quot;/&gt;
     &lt;/module&gt;
   &lt;/module&gt;
 &lt;/module&gt;
@@ -333,10 +337,13 @@ class Example5 {
 
   public void method0() {
     int mode = 0;
+    int x;
     switch (mode) {
       case 1:
-        int x = 1;
+        int y = 1;
         break;
+      case 2: {x = 1;}   // ok, RightCurly is in single line
+      case 3: int z = 0; {break;} // ok, the braces is not a first child of case
       default:
         x = 0;
     }
diff --git a/src/xdocs/checks/blocks/rightcurly.xml.template b/src/xdocs/checks/blocks/rightcurly.xml.template
index 6618086e1aa..6d17edde2e2 100644
--- a/src/xdocs/checks/blocks/rightcurly.xml.template
+++ b/src/xdocs/checks/blocks/rightcurly.xml.template
@@ -11,7 +11,7 @@
       <subsection name="Description" id="Description">
         <p>
           Checks the placement of right curly braces (<code>'}'</code>) for code blocks.
-          This check supports if-else, try-catch-finally blocks, switch statements,
+          This check supports if-else, try-catch-finally blocks, switch statements, switch cases,
           while-loops, for-loops, method definitions, class definitions, constructor definitions,
           instance, static initialization blocks, annotation definitions and enum definitions.
           For right curly brace of expression blocks of arrays, lambdas and class instances
@@ -65,7 +65,7 @@
           To configure the check with policy <code>alone</code> for
           <a href="https://docs.oracle.com/javase/tutorial/java/nutsandbolts/switch.html">
           Switch</a>
-          Statements:
+          Statements and Switch Cases:
         </p>
         <macro name="example">
             <param name="path"
@@ -100,7 +100,7 @@
           To configure the check with policy <code>alone_or_singleline</code> for
           <a href="https://docs.oracle.com/javase/tutorial/java/nutsandbolts/switch.html">
           Switch</a>
-          Statements:
+          Statements and Switch Cases:
         </p>
         <macro name="example">
             <param name="path"