Switchexpression#138
Conversation
|
todo :
|
|
I was making tests for enums JDefinedClass cl = root._class("ESwitch");
JMethod m = cl.method(JMod.PUBLIC | JMod.STATIC, Number.class, "daysIn");
JVar o = m.param(jcm.ref(Object.class), "o");
JSwitchExpression sw = JExpr._switch(o);
m.body()._return(sw);
sw._default().andNull()._throws(jcm, UnsupportedOperationException.class);
sw._case(JExpr.enumConstantRef(jcm.ref(EnumMonths.class), "JAN"))
.yield(JExpr.lit(31));
JDefinedClass ep = root._enum("EPeriod");
JEnumConstant yearConstant = ep.enumConstant("YEAR");
sw._case(yearConstant).yield(JExpr.lit(365));generates public class ESwitch {
public static Number daysIn(Object o) {
return switch (o) {
case EnumMonths.JAN ->
31;
case YEAR -> // <- error
365;
case null, default -> {
throw new UnsupportedOperationException();
}
}
;
}
}with the error
Should be |
block. Trying to add enum testing but result is failed
|
adding a syntaxic sugar in JCodemodel ///
/// reference a existing enum value
public @NonNull JEnumConstantRef ref(Enum<?> e) {
return JExpr.enumConstantRef(ref(e.getDeclaringClass()), e.name());
}This allows to rewrite JExpr.enumConstantRef(jcm.ref(EnumMonths.class),"JAN"); // old
jcm.ref(EnumMonths.JAN); // newAnd is more resilient to refactoring |
|
fixed aforementioned bug by adding in JSwitchExpression public JCaseStatic _case(@NonNull final JEnumConstant constantRef) {
return _case(JExpr.enumConstantRef(constantRef.type(), constantRef.name()));
}with that the switch on enum makes correct code. |
|
removing WiP, I think I've done my part, only issue I can think of is java version that requires a bump and prevent the CLI from working since it's java17 and java17 does not accept switch patterns :P |
|
possible solutions for the java version problem
example of uglyness : same code in new and old styles //length method of Object o
ret = switch(o){
case String s -> switch(s.toLowerCase()){
case "jan" -> 31;
default->s.length();
};
case Collection<?> c ->c.size();
case null, default -> 0;
};would become //length method of Object o
ret = new Callable<>(){
public void call(){
if(o==null) return 0;
if(o instanceof String){
String s = (String) o;
return new Callable<>(){
public void call(){
switch(s.toLowerCase()){
case "jan" : return 31; break;
default : return s.length;
}
}
}.call();
}
if(o instance of Collection) {
Collection c = (Collection) o;
return c.size();
}
return 0;
}
}.call(); |
low those tests are skipped.
removed java version spec in root pom
|
2026-05-14T12:12:17.8555234Z [ERROR] COMPILATION ERROR :
FFS !!!
I don't even know if my hacks work, the project fails for stupid reasons beforehand ! |
|
raah Java execution does not know of the "release" property. So I need to transmit it to the generator . But maven does not either ! So I can't activate a profile when java.version ≥ 21 because that's just not doable. I can activate a profile when java.version is set, or set TO 21 ; and I can activate a profile when JDK is ≥21 ; but the later will always be active on my java25 installation, even if I choose to build for java.version=17 ! so far I fixed the transmission, so that test generators that requires a higher java version than our java.version are skipped ; but I can't find how to make the java-21 specific classes ignored when running on java25 jdk with java.release=17 . |
|
I made too many rambles, here is the issues explained in simplest way : A method that I called is now deprecated in java 25. The replacement of that method does not exist in java 17, therefore I can't have same code for both releases without a deprecation call. Since this project generates code depending on java features, and the last LTS is 25 https://en.wikipedia.org/wiki/Java_version_history#Java_SE_25_(LTS) , this raises the question of maintaining the whole project backward-compatible. I think we should ditch 17 and 21 compatibility, only using the lat LTS and the LTS intermediate releases (so 25 and 26) New java features can't be tested on an old java version. So again, no more java17 as this is weights us down. Another possibility would be, to have dedicated submodules, in our case /java21 that depends on the original project (/jcodemodel) and add release-bound feature classes in them ; but that would still be a lot of hassle and a feeding ground for bugs, plus would force the user to be aware of internal changes |
|
ok so here is what I'm gonna do : Keep that branch on my side, close the PR, make a new one with only java17 switch expression ; make another branch and PR with java25 switchpattern. The new branch will be made with future switchpattern in mind. What about it @phax ? |
change : java21 required
Based on master
Implementation of #136
Remaining:
Done:
case null, default ->; so switchexpression allows to add to both null and default,sw._null().andDefault()._throws(…)case 1, 2 ->case Integer iand therefore add var-specificaddOn,yieldOn,throwOnto create the expression based on the matched variablei+1orthrow new Exception ("received"+i)whengenerator example :
https://github.com/glelouet/jcodemodel/blob/switchexpression/jcodemodeltests/src/main/java/com/helger/jcodemodel/tests/switchexpression/SwitchExpressionTestGen.java
result :
https://github.com/glelouet/jcodemodel/blob/switchexpression/jcodemodeltests/src/generated/javatest/com/helger/jcodemodel/tests/switchexpression/BasicSwitch.java