From 35c4666aa5319261072d471135a8dc6a9fd00832 Mon Sep 17 00:00:00 2001 From: Colin Alworth Date: Thu, 19 Dec 2024 08:36:34 -0600 Subject: [PATCH] Support JDT's implicit yield in switch statements (#10059) JDT generates a yield for arrow cases if the arrow points at a expression, even though the expression cannot be returned. Synthesize a block wrapping that expression as a statement, and add a break to the end of it. Fixes #10044 --- .../gwt/dev/jjs/impl/GwtAstBuilder.java | 8 +++- .../google/gwt/dev/jjs/test/Java17Test.java | 46 +++++++++++++++++++ .../google/gwt/dev/jjs/test/Java17Test.java | 3 ++ 3 files changed, 56 insertions(+), 1 deletion(-) diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/GwtAstBuilder.java b/dev/core/src/com/google/gwt/dev/jjs/impl/GwtAstBuilder.java index 354d9cdb65..6cf609c4f1 100644 --- a/dev/core/src/com/google/gwt/dev/jjs/impl/GwtAstBuilder.java +++ b/dev/core/src/com/google/gwt/dev/jjs/impl/GwtAstBuilder.java @@ -547,7 +547,13 @@ public void endVisit(YieldStatement x, BlockScope scope) { try { SourceInfo info = makeSourceInfo(x); JExpression expression = pop(x.expression); - push(new JYieldStatement(info, expression)); + if (x.switchExpression == null) { + // This is an implicit 'yield' in a case with an arrow - synthesize a break instead and + // wrap with a block so that the child count in JDT and GWT matches. + push(new JBlock(info, expression.makeStatement(), new JBreakStatement(info, null))); + } else { + push(new JYieldStatement(info, expression)); + } } catch (Throwable e) { throw translateException(x, e); } diff --git a/user/test-super/com/google/gwt/dev/jjs/super/com/google/gwt/dev/jjs/test/Java17Test.java b/user/test-super/com/google/gwt/dev/jjs/super/com/google/gwt/dev/jjs/test/Java17Test.java index fc238a981b..90960b0a11 100644 --- a/user/test-super/com/google/gwt/dev/jjs/super/com/google/gwt/dev/jjs/test/Java17Test.java +++ b/user/test-super/com/google/gwt/dev/jjs/super/com/google/gwt/dev/jjs/test/Java17Test.java @@ -494,4 +494,50 @@ public void testInlinedStringConstantsInCase() { }; assertEquals(4, value); } + + // https://github.com/gwtproject/gwt/issues/10044 + public void testCaseArrowLabelsVoidExpression() { + // Each switch is extracted to its own method to avoid the early return bug. + assertEquals("success", arrowWithVoidExpr()); + + // Arrow with non-void expr + assertEquals("success", arrowWithStringExpr()); + assertEquals("success", arrowWithIntExpr()); + + // Arrow with a statement - doesn't fail as part of this bug. This exists to verify + // that JDT won't give us a yield with a statement somehow. + assertEquals("success", arrowWithStatement()); + } + + private static String arrowWithVoidExpr() { + switch(0) { + case 0 -> assertTrue(true); + }; + return "success"; + } + + private static String arrowWithStringExpr() { + switch(0) { + case 0 -> new Object().toString(); + }; + return "success"; + } + + private static String arrowWithIntExpr() { + switch(0) { + case 0 -> new Object().hashCode(); + }; + return "success"; + } + + private static String arrowWithStatement() { + switch(0) { + case 0 -> { + if (true) { + new Object().toString(); + } + } + }; + return "success"; + } } diff --git a/user/test/com/google/gwt/dev/jjs/test/Java17Test.java b/user/test/com/google/gwt/dev/jjs/test/Java17Test.java index 39e0253397..844ff25c38 100644 --- a/user/test/com/google/gwt/dev/jjs/test/Java17Test.java +++ b/user/test/com/google/gwt/dev/jjs/test/Java17Test.java @@ -121,6 +121,9 @@ public void testSwitchExprInlining() { public void testInlinedStringConstantsInCase() { assertFalse(isGwtSourceLevel17()); } + public void testCaseArrowLabelsVoidExpression() { + assertFalse(isGwtSourceLevel17()); + } private boolean isGwtSourceLevel17() { return JUnitShell.getCompilerOptions().getSourceLevel().compareTo(SourceLevel.JAVA17) >= 0;