Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

"Cannot mix pattern with other case labels" Java 21 + preview feature #3043

Closed
tors42 opened this issue Feb 3, 2024 · 6 comments
Closed
Labels

Comments

@tors42
Copy link

tors42 commented Feb 3, 2024

src/main/java/pkg/Main.java

package pkg;

class Main {

    sealed interface OneTwoThree {}
    record One()   implements OneTwoThree {}
    record Two()   implements OneTwoThree {}
    record Three() implements OneTwoThree {}

    public static void main(String[] args) {
        OneTwoThree value = new Three();

        String message = switch(value) {
            case One one  -> "One!";
            case Two   _,
                 Three _  -> "Two or Three!";
        };

        System.out.println(message);
    }
}
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project>
  <modelVersion>4.0.0</modelVersion>

  <groupId>pkg</groupId>
  <artifactId>main</artifactId>
  <version>0.0.1-SNAPSHOT</version>

  <properties>
    <maven.compiler.release>21</maven.compiler.release>
  </properties>

  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>3.12.1</version>
        <configuration>
          <compilerArgs>
            <compilerArg>--enable-preview</compilerArg>
          </compilerArgs>
        </configuration>
      </plugin>
    </plugins>
  </build>
</project>

jdtls reports "Cannot mix pattern with other case labels" error,
while java happily runs:

$ java --enable-preview --source 21 src/main/java/pkg/Main.java
Note: src/main/java/pkg/Main.java uses preview features of Java SE 21.
Note: Recompile with -Xlint:preview for details.
Two or Three!
@tors42
Copy link
Author

tors42 commented Feb 4, 2024

I use latest jdtls snapshot (at time of writing jdt-language-server-1.33.0-202402030358),
launched through Neovim,
through plugin nvim-jdtls,
with Java 21.0.2

Many "movable parts" where things can go wrong... 😅
Hoping the Main.java file above is good enough to serve as possible reproducer 🤞

@tors42
Copy link
Author

tors42 commented Feb 5, 2024

Ah,
I searched for the "Cannot mix pattern with other case labels" and found it in eclipse-jdt/eclipse.jdt.core

  • an incremental or batch Java compiler that can run standalone or as part of the Eclipse IDE

I'll see if I can figure out how to launch that compiler on my Main.java,
probably better to report it in that repo... 🤔

Edit,
including a semi-successful way to reproduce with ecj (org.eclipse.jdt:ecj:3.36.0),
with a jshell script and docker.
"semi-successful" as this also reports error about source level 9 which I don't see from jdtls,
revealing that I don't know what I'm doing...
😜

ecj.jsh
if (! Files.exists(Path.of("ecj.jar"))) {
    Files.write(Path.of("ecj.jar"), URI.create(
        "https://repo1.maven.org/maven2/org/eclipse/jdt/ecj/3.36.0/ecj-3.36.0.jar"
        ).toURL().openStream().readAllBytes());
}
/env --class-path ecj.jar

Files.writeString(Path.of("Main.java"), """
    class Main {

        sealed interface OneTwoThree {}
        record One()   implements OneTwoThree {}
        record Two()   implements OneTwoThree {}
        record Three() implements OneTwoThree {}

        public static void main(String[] args) {
            OneTwoThree value = new Three();

            String message = switch(value) {
                case One one  -> "One!";
                case Two   _,
                     Three _  -> "Two or Three!";
            };

            System.out.println(message);
        }
    }
    """);

import org.eclipse.jdt.core.compiler.batch.BatchCompiler;
import org.eclipse.jdt.core.compiler.CompilationProgress;

class MyCompilationProgress extends CompilationProgress {
    public void begin(int remainingWork) {}
    public void done() {}
    public boolean isCanceled() { return false; }
    public void setTaskName(String name) { System.out.println("Task: " + name); }
    public void worked(int workIncrement, int remainingWork) {}
}

var out = new StringWriter();
var err = new StringWriter();

String command = "--enable-preview -source 21 Main.java";

//command = "-help"

boolean success = BatchCompiler.compile(
    command,
    new PrintWriter(out),
    new PrintWriter(err),
    new MyCompilationProgress()
    );

System.out.println(String.join("\n",
    success ? "Success!" : "Nope",
    out.toString(),
    err.toString()));

/exit
$ docker run --rm -i eclipse-temurin:21.0.2_13-jdk-alpine jshell - < ecj.jsh
Feb 05, 2024 2:41:02 PM java.util.prefs.FileSystemPreferences$1 run
INFO: Created user preferences directory.
Task: Beginning to compile
Task: Processing /Main.java
Nope

----------
1. ERROR in /Main.java (at line 13)
	case Two   _,
	    ^^^^^^^
Cannot mix pattern with other case labels
----------
2. ERROR in /Main.java (at line 13)
	case Two   _,
	          ^
'_' is a keyword from source level 9 onwards, cannot be used as identifier
----------
3. ERROR in /Main.java (at line 14)
	Three _  -> "Two or Three!";
	     ^
'_' is a keyword from source level 9 onwards, cannot be used as identifier
----------
3 problems (3 errors)

@fbricon
Copy link
Contributor

fbricon commented Feb 5, 2024

That's a question for @datho7561, since he implemented unnamed variables support in JDT

@datho7561
Copy link
Contributor

I split the "unnamed variables and patterns" feature into two separate PRs, one for the base feature and one for supporting lists of patterns in case statements. The second part hasn't been reviewed or merged yet:

They are hesitant about reviewing my PR upstream since they want to rewrite a lot of the code that my PR touches before merging my PR. I guess we should consider merging my PR into our fork @rgrunber . My main concern is that this means maintaining our fork gets harder once they start making the changes to the code that conflict with my PR.

@tors42
Copy link
Author

tors42 commented Mar 27, 2024

Today I tried with jdt-language-server-1.34.0-202403261717 ,
and I no longer get the error message! Great stuff!

@tors42 tors42 closed this as completed Mar 27, 2024
@fbricon fbricon added this to the End March 2024 milestone Mar 27, 2024
@fbricon fbricon added the bug label Mar 27, 2024
@nithin-mk
Copy link

I use latest jdtls snapshot (at time of writing jdt-language-server-1.33.0-202402030358), launched through Neovim, through plugin nvim-jdtls, with Java 21.0.2

Many "movable parts" where things can go wrong... 😅 Hoping the Main.java file above is good enough to serve as possible reproducer 🤞

@tors42 I too use the same versions of all these software, except my JDTLS version is 1.35.0, but still I can't get JDK 21 support. I get error messages like "String cannot be resolved to a type", etc. Any specific configuration to be done?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

4 participants