Java 21 pattern matching false positives

  • ALM used: GitHub
  • CI system used: GHA
  • Languages used: Java 21

With the following code:

sealed interface Animal permits Cat, Dog {}
record Cat() implements Animal { }
record Dog() implements Animal { }

public static int getLives(Animal animal) {
    return switch (animal) {
        case Cat ignored -> 7;
        case Dog ignored -> 1;
    }
}

SonarCloud will complain that:

  1. java:S131 Add a default case for this switch. Thanks to sealed interfaces this pattern match is exhaustive and enforced by the compiler, so no default case is required.
  2. java:S1481 Remove this unused “ignored” local variable. It cannot be removed (unless using Java 21 preview, in which case it could be replaced by an underscore).
  3. java:S1301 Replace this “switch” statement by “if” statements to increase readability. With a switch over a sealed interface we gain exhaustive matching, which can be preferable over ifs.

Also, this is not shown in the example above, but if we had a case statement with an empty body (e.g. case Something something -> { }, SonarCloud would complain that:

  1. java:S108 Either remove or fill this block of code. With exhaustive pattern matching it is not possible to remove this case statement - and filling the block of code depends on the use case.
1 Like

Hey there.

I’ve moved your post to the section on reporting false-positives. Can you update your post with the specific Rule IDs concerned? Thanks!

Hi Colin, updated my original post. Thank you!

Thanks! One ticket already exists.

SONARJAVA-4461

I’ll refer the other cases to our team of experts. Stay tuned!

Hey @kyris ,

Thanks a lot for the feedback, it is spot on as we are working these days on improving our support of Java 21. I created multiple tickets thanks to you. Thanks, @Colin, for identifying the first one as well!

Here are the tickets and comments related to what you reported:

  • java:S108: Either remove or fill this block of code

    • As mentioned in its description, this rule will not raise issues if there is a comment inside the empty block. We believe that empty blocks should contain a comment explaining why there are no instructions in this case, and I feel it’s also valuable for switch statements, even when switching over sealed classes. I would therefore not consider this as an FP. Taking your sealed class example, this would be valid:
    public static void petAnimal(Animal animal) {
      switch (animal) {
        case Cat maurice -> { /* cats are cats and do not accept to be pet */ }
        case Dog doug -> doug.like();
      }
    }
    
  • java:S131: “switch” statements should have “default” clauses

    • SONARJAVA-4908 - FP on S131 when using switch statement on sealed classes
  • java:S1481: Unused local variables should be removed

    • SONARJAVA-4907 - FP on S1481 when using type pattern matching in case clauses of a switch
  • java:S1301: “switch” statements should have at least 3 “case” clauses

    • SONARJAVA-4441 - FP on S1301 [Java 14+] for switch statements with a case containing multiple labels (known issue)
    • SONARJAVA-4461 - FP on S1301 for small switch cases with new syntax -> (known issue)
    • SONARJAVA-4904 - FP on S1301 when using switch statement with type patterns (new issue)

Cheers,
Michael

Thank you Michael, wasn’t aware about the comment thing in S108!

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.