Repository: checkstyle/checkstyle

Problem statement:
MissingSwitchDefault : False positive when `case null` in switch labeled statement group
Check documentation : https://checkstyle.org/checks/coding/missingswitchdefault.html#MissingSwitchDefault

---
```
PS D:\CS\test> javac src/Test.java                                               
PS D:\CS\test> cat src/Test.java                                                 
public class Test {
    void m(E i) {
        switch (i) {  // violation
            case FIRST :
            case SECOND :
            case null :
                System.out.println("NULL first and second");
        }
    }
    enum E {
        FIRST, SECOND
    }
}
PS D:\CS\test> cat config.xml                                                    
<?xml version="1.0"?>
<!DOCTYPE module PUBLIC
          "-//Checkstyle//DTD Checkstyle Configuration 1.3//EN"
          "https://checkstyle.org/dtds/configuration_1_3.dtd">

<module name="Checker">
  <module name="TreeWalker">
            <module name="MissingSwitchDefault"/>
        </module>
</module>
PS D:\CS\test> java  -jar checkstyle-10.17.0-all.jar -c config.xml  src/Test.java
Starting audit...
[ERROR] D:\CS\test\src\Test.java:3:9: switch without "default" clause. [MissingSwitchDefault]
Audit done.
Checkstyle ends with 1 errors.
PS D:\CS\test> 

```

---
I expect no violation because there is a case null in the switch so exhaustiveness is being checked. the issue is that the check doesn't detect case null if it is in a labeled group.


Hints:

Patch:
diff --git a/src/main/java/com/puppycrawl/tools/checkstyle/checks/coding/MissingSwitchDefaultCheck.java b/src/main/java/com/puppycrawl/tools/checkstyle/checks/coding/MissingSwitchDefaultCheck.java
--- a/src/main/java/com/puppycrawl/tools/checkstyle/checks/coding/MissingSwitchDefaultCheck.java
+++ b/src/main/java/com/puppycrawl/tools/checkstyle/checks/coding/MissingSwitchDefaultCheck.java
@@ -176,13 +176,13 @@ private static boolean isSwitchExpression(DetailAST ast) {
     /**
      * Checks if the case contains null label.
      *
-     * @param ast the switch statement we are checking
+     * @param detailAST the switch statement we are checking
      * @return returnValue the ast of null label
      */
-    private static boolean hasNullCaseLabel(DetailAST ast) {
-        final DetailAST firstChild = ast.getFirstChild();
-        return firstChild != null
-                && TokenUtil.isOfType(firstChild.getFirstChild(), TokenTypes.LITERAL_NULL);
-
+    private static boolean hasNullCaseLabel(DetailAST detailAST) {
+        return TokenUtil.findFirstTokenByPredicate(detailAST.getParent(), ast -> {
+            final DetailAST expr = ast.findFirstToken(TokenTypes.EXPR);
+            return expr != null && expr.findFirstToken(TokenTypes.LITERAL_NULL) != null;
+        }).isPresent();
     }
 }


Test patch:
diff --git a/src/test/resources-noncompilable/com/puppycrawl/tools/checkstyle/checks/coding/missingswitchdefault/InputMissingSwitchDefaultCheckNullCaseLabel.java b/src/test/resources-noncompilable/com/puppycrawl/tools/checkstyle/checks/coding/missingswitchdefault/InputMissingSwitchDefaultCheckNullCaseLabel.java
--- a/src/test/resources-noncompilable/com/puppycrawl/tools/checkstyle/checks/coding/missingswitchdefault/InputMissingSwitchDefaultCheckNullCaseLabel.java
+++ b/src/test/resources-noncompilable/com/puppycrawl/tools/checkstyle/checks/coding/missingswitchdefault/InputMissingSwitchDefaultCheckNullCaseLabel.java
@@ -15,6 +15,24 @@ public void switchWithNullLabelTest(SwitchInput i) {
             case SECOND: counter--;
             case null: counter=counter+2;
         }
+        switch (i) {
+            case FIRST:
+            case SECOND:
+            case null:
+                counter=counter+2;
+        }
+        switch (i) {
+            case FIRST:
+            case null:
+            case SECOND:
+                counter=counter+2;
+        }
+        switch (i) {
+            case null:
+            case FIRST:
+            case SECOND:
+                counter=counter+2;
+        }
     }
     enum SwitchInput {
         FIRST,