Skip to content

Support Java 14 switch expressions #126

@octylFractal

Description

@octylFractal

Switch expressions came with Java 14, using them results in this stacktrace: https://gist.github.com/octylFractal/f30df05af3fc15fbf01a1dbc1d136b39

[INFO] [REDACTED]:75:85:expecting COLON, found ';'
[INFO] Instrumentation error
com.atlassian.clover.api.CloverException: [REDACTED]:75:85:expecting COLON, found ';'
    at com.atlassian.clover.instr.java.Instrumenter.instrument (Instrumenter.java:159)
    at com.atlassian.clover.CloverInstr.execute (CloverInstr.java:76)
    at com.atlassian.clover.CloverInstr.mainImpl (CloverInstr.java:54)
...
Caused by: clover.antlr.MismatchedTokenException: expecting COLON, found ';'
    at clover.antlr.Parser.match (Parser.java:211)
    at com.atlassian.clover.instr.java.JavaRecognizer.aCase (JavaRecognizer.java:4330)
    at com.atlassian.clover.instr.java.JavaRecognizer.casesGroup (JavaRecognizer.java:4161)
    at com.atlassian.clover.instr.java.JavaRecognizer.statement (JavaRecognizer.java:3640)
    at com.atlassian.clover.instr.java.JavaRecognizer.compoundStatement (JavaRecognizer.java:4050)

The code snippet that causes this error:

switch (result) {
    case SUCCESS -> System.err.println("Success!");
    case FAILURE -> System.err.println("Failure.");
}

another example with blocks:

int j = switch (day) {
    case MONDAY  -> 0;
    case TUESDAY -> 1;
    default      -> {
        int k = day.toString().length();
        int result = f(k);
        yield result;
    }
};

Old style can also leverage the yield and value returned by switch:

A switch expression can, like a switch statement, also use a traditional switch block with "case L:" switch labels (implying fall through semantics). In this case, values are yielded using the new yield statement:

int result = switch (s) {
    case "a": 
        yield 1;
    case "b":
        yield 2;
    default:
        yield -1;
};

Specification: https://openjdk.org/jeps/361

To be implemented:

  • "case -> " with "default -> " as an alternative switch block grammar (both old and new cannot be mixed?)
  • multiple values separated by comma in "case "
  • the CAN return a value -> probably have to be wrapped in lambdaInc() like normal lambdas
  • the entire switch expression CAN return a value,
    ** so "a = switch(b) { ...}" must work -> switch expression rule as one of the options for the 'expression' rule
    ** also passing switch value to a method "foo(switch(b) { ...})" must be handled
  • blocks with 'yield ;' keyword
  • old-style switch with "case:" and yield

What needs no instrumentation:

  • scope of variable flowing to next case statements
  • don't need to check if all possible options were exhausted in a switch
  • any recognition of generic types

Metadata

Metadata

Labels

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions