Repository: checkstyle/checkstyle (Java)

Issue:
Add Check Support for Java 21 Pattern Matching for Switch Syntax: WhitespaceAfter
child of #14961 

I have read check documentation: https://checkstyle.org/checks/whitespace/whitespaceafter.html#WhitespaceAfter
I have downloaded the latest checkstyle from: https://checkstyle.org/cmdline.html#Download_and_Run
I have executed the cli and showed it below, as cli describes the problem better than 1,000 words

```

➜  src 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="WhitespaceAfter"/>
    </module>
</module>
➜  src cat Test.java 
record ColoredPoint(int p, int x, String c) { }

public class Test {

    void test(Object obj) {
        int y = 0;
        if(y>=2) { }            // violation
        switch (obj) {
            case ColoredPoint(int x, _, _) when(x >= 2) -> {}     // expected violation

            default -> {}
        }
    }
}
➜  src javac --enable-preview --release 21 Test.java                        
Note: Test.java uses preview features of Java SE 21.
Note: Recompile with -Xlint:preview for details.
➜  src java -jar checkstyle-10.18.1-SNAPSHOT-all.jar -c config.xml Test.java
Starting audit...
[ERROR] /home/nick/IdeaProjects/tester/src/Test.java:7:9: 'if' is not followed by whitespace. [WhitespaceAfter]
Audit done.
Checkstyle ends with 1 errors.


```
---

**Describe what you want in detail**

violation on `when` because there is no white space after when and before the parens



Discussion:
Token to add is `LITERAL_WHEN` and should be able to turn on/off.

I am good with this.
I have updated the example now that we have added the `EXPR` token, this is a false negative.
Issue is not done until subsequent PRs are merged for the IT



Patch:
diff --git a/src/main/java/com/puppycrawl/tools/checkstyle/checks/whitespace/WhitespaceAfterCheck.java b/src/main/java/com/puppycrawl/tools/checkstyle/checks/whitespace/WhitespaceAfterCheck.java
index e1bea5045d7..b04e8ccb8be 100644
--- a/src/main/java/com/puppycrawl/tools/checkstyle/checks/whitespace/WhitespaceAfterCheck.java
+++ b/src/main/java/com/puppycrawl/tools/checkstyle/checks/whitespace/WhitespaceAfterCheck.java
@@ -76,7 +76,9 @@
  * <a href="https://checkstyle.org/apidocs/com/puppycrawl/tools/checkstyle/api/TokenTypes.html#LITERAL_CASE">
  * LITERAL_CASE</a>,
  * <a href="https://checkstyle.org/apidocs/com/puppycrawl/tools/checkstyle/api/TokenTypes.html#LAMBDA">
- * LAMBDA</a>.
+ * LAMBDA</a>,
+ * <a href="https://checkstyle.org/apidocs/com/puppycrawl/tools/checkstyle/api/TokenTypes.html#LITERAL_WHEN">
+ * LITERAL_WHEN</a>.
  * </li>
  * </ul>
  * <p>
@@ -139,6 +141,7 @@ public int[] getAcceptableTokens() {
             TokenTypes.LITERAL_TRY,
             TokenTypes.LITERAL_CASE,
             TokenTypes.LAMBDA,
+            TokenTypes.LITERAL_WHEN,
         };
     }
 
diff --git a/src/main/resources/com/puppycrawl/tools/checkstyle/meta/checks/whitespace/WhitespaceAfterCheck.xml b/src/main/resources/com/puppycrawl/tools/checkstyle/meta/checks/whitespace/WhitespaceAfterCheck.xml
index 60623223295..7321a7031a0 100644
--- a/src/main/resources/com/puppycrawl/tools/checkstyle/meta/checks/whitespace/WhitespaceAfterCheck.xml
+++ b/src/main/resources/com/puppycrawl/tools/checkstyle/meta/checks/whitespace/WhitespaceAfterCheck.xml
@@ -12,7 +12,7 @@
  EmptyForIteratorPad&lt;/a&gt; to validate empty for iterators.
  &lt;/p&gt;</description>
          <properties>
-            <property default-value="COMMA,SEMI,TYPECAST,LITERAL_IF,LITERAL_ELSE,LITERAL_WHILE,LITERAL_DO,LITERAL_FOR,LITERAL_FINALLY,LITERAL_RETURN,LITERAL_YIELD,LITERAL_CATCH,DO_WHILE,ELLIPSIS,LITERAL_SWITCH,LITERAL_SYNCHRONIZED,LITERAL_TRY,LITERAL_CASE,LAMBDA"
+            <property default-value="COMMA,SEMI,TYPECAST,LITERAL_IF,LITERAL_ELSE,LITERAL_WHILE,LITERAL_DO,LITERAL_FOR,LITERAL_FINALLY,LITERAL_RETURN,LITERAL_YIELD,LITERAL_CATCH,DO_WHILE,ELLIPSIS,LITERAL_SWITCH,LITERAL_SYNCHRONIZED,LITERAL_TRY,LITERAL_CASE,LAMBDA,LITERAL_WHEN"
                       name="tokens"
                       type="java.lang.String[]"
                       validation-type="tokenSet">
diff --git a/src/main/resources/google_checks.xml b/src/main/resources/google_checks.xml
index 050c394289d..901c48e528d 100644
--- a/src/main/resources/google_checks.xml
+++ b/src/main/resources/google_checks.xml
@@ -110,7 +110,7 @@
                value="COMMA, SEMI, TYPECAST, LITERAL_IF, LITERAL_ELSE, LITERAL_RETURN,
                     LITERAL_WHILE, LITERAL_DO, LITERAL_FOR, LITERAL_FINALLY, DO_WHILE, ELLIPSIS,
                     LITERAL_SWITCH, LITERAL_SYNCHRONIZED, LITERAL_TRY, LITERAL_CATCH, LAMBDA,
-                    LITERAL_YIELD, LITERAL_CASE"/>
+                    LITERAL_YIELD, LITERAL_CASE, LITERAL_WHEN"/>
     </module>
     <module name="WhitespaceAround">
       <property name="allowEmptyConstructors" value="true"/>
diff --git a/src/xdocs/checks/whitespace/whitespaceafter.xml b/src/xdocs/checks/whitespace/whitespaceafter.xml
index 8487962adfc..5916c3009a1 100644
--- a/src/xdocs/checks/whitespace/whitespaceafter.xml
+++ b/src/xdocs/checks/whitespace/whitespaceafter.xml
@@ -69,6 +69,8 @@
                     LITERAL_CASE</a>
                 , <a href="../../apidocs/com/puppycrawl/tools/checkstyle/api/TokenTypes.html#LAMBDA">
                     LAMBDA</a>
+                , <a href="../../apidocs/com/puppycrawl/tools/checkstyle/api/TokenTypes.html#LITERAL_WHEN">
+                    LITERAL_WHEN</a>
                   .
               </td>
               <td>
@@ -110,6 +112,8 @@
                     LITERAL_CASE</a>
                 , <a href="../../apidocs/com/puppycrawl/tools/checkstyle/api/TokenTypes.html#LAMBDA">
                     LAMBDA</a>
+                , <a href="../../apidocs/com/puppycrawl/tools/checkstyle/api/TokenTypes.html#LITERAL_WHEN">
+                    LITERAL_WHEN</a>
                   .
               </td>
               <td>3.0</td>


Test patch:
diff --git a/src/test/java/com/puppycrawl/tools/checkstyle/checks/whitespace/WhitespaceAfterCheckTest.java b/src/test/java/com/puppycrawl/tools/checkstyle/checks/whitespace/WhitespaceAfterCheckTest.java
index 1c78efc9b9a..5f25d673aeb 100644
--- a/src/test/java/com/puppycrawl/tools/checkstyle/checks/whitespace/WhitespaceAfterCheckTest.java
+++ b/src/test/java/com/puppycrawl/tools/checkstyle/checks/whitespace/WhitespaceAfterCheckTest.java
@@ -329,4 +329,19 @@ public void testWhitespaceAfterWithEmoji() throws Exception {
         verifyWithInlineConfigParser(
             getPath("InputWhitespaceAfterWithEmoji.java"), expected);
     }
+
+    @Test
+    public void testLiteralWhen() throws Exception {
+        final String[] expected = {
+            "14:28: " + getCheckMessage(MSG_WS_NOT_FOLLOWED, "when"),
+            "16:27: " + getCheckMessage(MSG_WS_NOT_FOLLOWED, "when"),
+            "18:39: " + getCheckMessage(MSG_WS_NOT_FOLLOWED, "when"),
+            "20:39: " + getCheckMessage(MSG_WS_NOT_FOLLOWED, "when"),
+            "35:28: " + getCheckMessage(MSG_WS_NOT_FOLLOWED, "when"),
+            "45:21: " + getCheckMessage(MSG_WS_NOT_FOLLOWED, "when"),
+        };
+        verifyWithInlineConfigParser(
+            getNonCompilablePath("InputWhitespaceAfterLiteralWhen.java"),
+            expected);
+    }
 }
diff --git a/src/test/resources-noncompilable/com/puppycrawl/tools/checkstyle/checks/whitespace/whitespaceafter/InputWhitespaceAfterLiteralWhen.java b/src/test/resources-noncompilable/com/puppycrawl/tools/checkstyle/checks/whitespace/whitespaceafter/InputWhitespaceAfterLiteralWhen.java
new file mode 100644
index 00000000000..e83bc559e3e
--- /dev/null
+++ b/src/test/resources-noncompilable/com/puppycrawl/tools/checkstyle/checks/whitespace/whitespaceafter/InputWhitespaceAfterLiteralWhen.java
@@ -0,0 +1,50 @@
+/*
+WhitespaceAfter
+tokens = LITERAL_WHEN
+
+*/
+
+//non-compiled with javac: Compilable with Java21
+package com.puppycrawl.tools.checkstyle.checks.whitespace.whitespaceafter;
+
+public class InputWhitespaceAfterLiteralWhen {
+
+    void test(Object o) {
+        switch (o) {
+            case Integer i when(i == 0) -> {} // violation, ''when' is not followed by whitespace'
+            // violation below, ''when' is not followed by whitespace'
+            case String s when(s.equals("a")) -> {}
+            // violation below, ''when' is not followed by whitespace'
+            case Point(int x, int y ) when(x>=0 && y >=0) -> {}
+            // violation below, ''when' is not followed by whitespace'
+            case Point(int x, int y ) when!(x>=0 && y >=0) -> {}
+            default -> {}
+        }
+
+        switch (o) {
+            case Integer i when (i == 0) -> {}
+            case String s when (s.equals("a")) -> {}
+            case Point(int x, int y ) when (x>=0 && y >=0) -> {}
+            default -> {}
+        }
+    }
+
+    void testLineBreaks(Object o) {
+        switch (o) {
+            // violation below, ''when' is not followed by whitespace'
+            case Integer i when(
+                    i == 0) -> {}
+            case String s
+                    when
+                    (s.equals("a")) -> {}
+            case Point(int x, int y )
+                    when
+                    (x>=0 && y >=0) -> {}
+            case Point(int x, int y )
+                    // violation below, ''when' is not followed by whitespace'
+                    when!(x>=0 && y >=0) -> {}
+            default -> {}
+        }
+    }
+    record Point(int x, int y) {}
+}