| We're trying to make `switch`es simpler to understand at a glance. | 
 | Misunderstanding the control flow of a `switch` is a common source of bugs. | 
 |  | 
 | As part of this simplification, new-style arrow (`->`) switches are encouraged | 
 | instead of old-style colon (`:`) switches. And where possible, neighboring cases | 
 | are grouped together (e.g. `case A, B, C`). | 
 |  | 
 | ### Old-style colon (`:`) `switch`es: | 
 |  | 
 | *   Have a colon between the `case` and the `case`'s code. For example, `case | 
 |     HEARTS:` | 
 | *   Because of the potential for fall-through, it takes time and cognitive load | 
 |     to understand the control flow. When a `switch` block is large, just | 
 |     skimming each `case` can be toilsome. Fall-through can also be conditional | 
 |     (see example 5. below). In this scenario, one would potentially need to | 
 |     reason about all possible flows for each `case`. When conditionally | 
 |     falling-through multiple `case`s, the number of potential control flows can | 
 |     grow rapidly | 
 | *   Lexical scopes overlap, which can lead to surprising behaviors: definitions | 
 |     of local variables from earlier `case`s are propagated down to later | 
 |     `case`s, however the *values* that initialize those local variables do not | 
 |     propagate in the same way | 
 |  | 
 | ### New-style arrow (`->`) `switch`es: | 
 |  | 
 | *   Have an arrow between the `case` and the `case`'s code. For example, `case | 
 |     HEARTS ->` | 
 | *   No `case`s fall through; no control flow analysis needed | 
 | *   Safely and easily reorder `case`s (within a `switch`) | 
 | *   Lexical scopes are isolated between different `case`s; if you define a local | 
 |     variable within a `case`, it can only be used within that specific `case`. | 
 |  | 
 | ### Examples | 
 |  | 
 | #### 1. Eliminate fall through | 
 |  | 
 | ``` {.bad} | 
 | enum Suit {HEARTS, CLUBS, SPADES, DIAMONDS}; | 
 |  | 
 | private void foo(Suit suit) { | 
 |   switch(suit) { | 
 |     case HEARTS: | 
 |       System.out.println("Red hearts"); | 
 |       break; | 
 |     case DIAMONDS: | 
 |       System.out.println("Red diamonds"); | 
 |       break; | 
 |     case SPADES: | 
 |     // Fall through | 
 |     case CLUBS: | 
 |       bar(); | 
 |       System.out.println("Black suit"); | 
 |     } | 
 | } | 
 | ``` | 
 |  | 
 | Which can be simplified by grouping and using a new-style switch: | 
 |  | 
 | ``` {.good} | 
 | enum Suit {HEARTS, CLUBS, SPADES, DIAMONDS}; | 
 |  | 
 | private void foo(Suit suit) { | 
 |   switch(suit) { | 
 |     case HEARTS -> System.out.println("Red hearts"); | 
 |     case DIAMONDS -> System.out.println("Red diamonds"); | 
 |     case SPADES, CLUBS -> { | 
 |       bar(); | 
 |       System.out.println("Black suit"); | 
 |     } | 
 |   } | 
 | } | 
 | ``` | 
 |  | 
 | #### 2. `return switch ...` | 
 |  | 
 | Sometimes `switch` is used with a `return` for each `case`, like this: | 
 |  | 
 | ``` {.bad} | 
 | enum SideOfCoin {OBVERSE, REVERSE}; | 
 |  | 
 | private String renderName(SideOfCoin sideOfCoin) { | 
 |   switch(sideOfCoin) { | 
 |     case OBVERSE: | 
 |       return "Heads"; | 
 |     case REVERSE: | 
 |       return "Tails"; | 
 |     } | 
 |     // This should never happen, but removing this will cause a compile-time error | 
 |     throw new RuntimeException("Unknown side of coin"); | 
 | } | 
 | ``` | 
 |  | 
 | Note that even though a `case` is present for each possible value of the `enum`, | 
 | a boilerplate "should never happen" clause is still needed. The transformed code | 
 | is simpler and doesn't need a "should never happen" clause. | 
 |  | 
 | ``` | 
 | enum SideOfCoin {OBVERSE, REVERSE}; | 
 |  | 
 | private String renderName(SideOfCoin sideOfCoin) { | 
 |   return switch(sideOfCoin) { | 
 |     case OBVERSE -> "Heads"; | 
 |     case REVERSE -> "Tails"; | 
 |   }; | 
 | } | 
 | ``` | 
 |  | 
 | If you nevertheless wish to define an explicit "should never happen" clause, | 
 | this can be accomplished by placing the logic inside a `default` case. For | 
 | example: | 
 |  | 
 | ``` | 
 | enum SideOfCoin {OBVERSE, REVERSE}; | 
 |  | 
 | private String foo(SideOfCoin sideOfCoin) { | 
 |   return switch(sideOfCoin) { | 
 |     case OBVERSE -> "Heads"; | 
 |     case REVERSE -> "Tails"; | 
 |     default -> throw new RuntimeException("Unknown side of coin"); // should never happen | 
 |   }; | 
 | } | 
 | ``` | 
 |  | 
 | When the checker detects an existing `default` that appears to be redundant, it | 
 | may suggest a secondary auto-fix which removes the redundant `default` and its | 
 | code (if any). | 
 |  | 
 | #### 3. Assignment `switch` | 
 |  | 
 | If every branch of a `switch` is making an assignment to the same variable, the | 
 | code can be simplified into a combined assignment and `switch`: | 
 |  | 
 | ``` {.bad} | 
 | enum Suit {HEARTS, CLUBS, SPADES, DIAMONDS}; | 
 |  | 
 | int score = 0; | 
 |  | 
 | private void updateScore(Suit suit) { | 
 |   switch(suit) { | 
 |     case HEARTS: | 
 |     // Fall thru | 
 |     case DIAMONDS: | 
 |       score += -1; | 
 |       break; | 
 |     case SPADES: | 
 |       score += 2; | 
 |       break; | 
 |     case CLUBS: | 
 |       score += 3; | 
 |     } | 
 | } | 
 | ``` | 
 |  | 
 | This can be simplified as follows: | 
 |  | 
 | ``` | 
 | enum Suit {HEARTS, CLUBS, SPADES, DIAMONDS}; | 
 |  | 
 | int score = 0; | 
 |  | 
 | private void updateScore(Suit suit) { | 
 |   score += switch(suit) { | 
 |     case HEARTS, DIAMONDS -> -1; | 
 |     case SPADES -> 2; | 
 |     case CLUBS -> 3; | 
 |   }; | 
 | } | 
 | ``` | 
 |  | 
 | Taking this one step further: if a local variable is defined, and then | 
 | immediately followed by a `switch` in which every `case` assigns to that same | 
 | variable, then all three (the `switch`, the variable declaration, and the | 
 | assignment) can be merged: | 
 |  | 
 | ``` {.bad} | 
 | enum Suit {HEARTS, CLUBS, SPADES, DIAMONDS}; | 
 |  | 
 | private void updateStatus(Suit suit) { | 
 |   int score; | 
 |  | 
 |   switch(suit) { | 
 |     case HEARTS: | 
 |     // Fall thru | 
 |     case DIAMONDS: | 
 |       score = 1; | 
 |       break; | 
 |     case SPADES: | 
 |       score = 2; | 
 |       break; | 
 |     case CLUBS: | 
 |       score = 3; | 
 |     } | 
 |   ... | 
 |  | 
 | } | 
 | ``` | 
 |  | 
 | Becomes: | 
 |  | 
 | ``` | 
 | enum Suit {HEARTS, CLUBS, SPADES, DIAMONDS}; | 
 |  | 
 | private void updateStatus(Suit suit) { | 
 |   int score = switch(suit) { | 
 |     case HEARTS, DIAMONDS -> 1; | 
 |     case SPADES -> 2; | 
 |     case CLUBS -> 3; | 
 |   }; | 
 |   ... | 
 | } | 
 | ``` | 
 |  | 
 | #### 4. Just converting to new arrow `switch` | 
 |  | 
 | Even when the simplifications discussed above are not applicable, conversion to | 
 | new arrow `switch`es can be automated by this checker: | 
 |  | 
 | ``` {.bad} | 
 | enum Suit {HEARTS, CLUBS, SPADES, DIAMONDS}; | 
 |  | 
 | private void processEvent(Suit suit) { | 
 |     switch (suit) { | 
 |       case CLUBS: | 
 |         String message = "hello"; | 
 |         var anotherMessage = "salut"; | 
 |         processMessages(message, anotherMessage); | 
 |         break; | 
 |       case DIAMONDS: | 
 |         anotherMessage = "bonjour"; | 
 |         processMessage(anotherMessage); | 
 |     } | 
 | } | 
 | ``` | 
 |  | 
 | Note that the local variables referenced in multiple cases are hoisted up out of | 
 | the `switch` statement, and `var` declarations are converted to explicit types, | 
 | resulting in: | 
 |  | 
 | ``` | 
 | enum Suit {HEARTS, CLUBS, SPADES, DIAMONDS}; | 
 |  | 
 | private void processEvent(Suit suit) { | 
 |     String anotherMessage; | 
 |     switch (suit) { | 
 |       case CLUBS -> { | 
 |         String message = "hello"; | 
 |         anotherMessage = "salut"; | 
 |         processMessages(message, anotherMessage); | 
 |       } | 
 |       case DIAMONDS -> { | 
 |         anotherMessage = "bonjour"; | 
 |         processMessage(anotherMessage); | 
 |       } | 
 |     } | 
 | } | 
 | ``` | 
 |  | 
 | #### 5. Complex control flows | 
 |  | 
 | Here's an example of a complex statement `switch` with conditional fall-through | 
 | and various control flows. Unfortunately, the checker does not currently have | 
 | the ability to automatically convert such code to new-style arrow `switch`es. | 
 | Manually converting the code could be a good opportunity to improve its | 
 | readability. | 
 |  | 
 | How many potential execution paths can you spot? | 
 |  | 
 | ``` {.bad} | 
 | enum Suit {HEARTS, CLUBS, SPADES, DIAMONDS}; | 
 |  | 
 | private int foo(Suit suit){ | 
 |   switch(suit) { | 
 |     case HEARTS: | 
 |       if (bar()) { | 
 |         break; | 
 |       } | 
 |     // Fall through | 
 |     case CLUBS: | 
 |       if (baz()) { | 
 |         return 1; | 
 |       } else if (baz2()) { | 
 |         throw new AssertionError(...); | 
 |       } | 
 |     // Fall through | 
 |     case SPADES: | 
 |     // Fall through | 
 |     case DIAMONDS: | 
 |       return 0; | 
 |   } | 
 |   return -1; | 
 | } | 
 | ``` |