aboutsummaryrefslogtreecommitdiffstats
path: root/tests/features1919
diff options
context:
space:
mode:
Diffstat (limited to 'tests/features1919')
-rw-r--r--tests/features1919/java19/SwitchPatternPreview3Aspect.aj88
-rw-r--r--tests/features1919/java19/SwitchPatternPreview3Error1.java13
-rw-r--r--tests/features1919/java19/SwitchPatternPreview3Error2.java21
-rw-r--r--tests/features1919/java19/SwitchPatternPreview3OK.java172
4 files changed, 294 insertions, 0 deletions
diff --git a/tests/features1919/java19/SwitchPatternPreview3Aspect.aj b/tests/features1919/java19/SwitchPatternPreview3Aspect.aj
new file mode 100644
index 000000000..ae147dad7
--- /dev/null
+++ b/tests/features1919/java19/SwitchPatternPreview3Aspect.aj
@@ -0,0 +1,88 @@
+import java.util.List;
+import java.util.Locale;
+
+aspect SwitchPatternPreview3Aspect {
+ Object around(Object o) : execution(* doSomethingWithObject(*)) && args(o) {
+ System.out.println(switch (o) {
+ case null -> "null";
+ case Integer i -> String.format("int %d", i);
+ case Long l -> String.format("long %d", l);
+ case Double d -> String.format(Locale.ENGLISH, "double %f", d);
+ case String s -> String.format("String %s", s);
+ default -> o.toString();
+ });
+ return proceed(o);
+ }
+
+ before(Shape s) : execution(* doSomethingWithShape(*)) && args(s) {
+ System.out.println(switch (s) {
+ case Circle c when (c.calculateArea() > 100) -> "Large circle";
+ case Circle c -> "Small circle";
+ default -> "Non-circle";
+ });
+ }
+
+ after(S s) : execution(* doSomethingWithSealedClass(*)) && args(s) {
+ System.out.println(switch (s) {
+ case A a -> "Sealed sub-class A";
+ case B b -> "Sealed sub-class B";
+ case C c -> "Sealed sub-record C";
+ });
+ }
+
+ Object around(Integer i): execution(* doSomethingWithInteger(*)) && args(i) {
+ System.out.println(
+ switch (i) {
+ case null -> "value unavailable: " + i;
+ case -1, 1 -> "absolute value 1: " + i;
+ case Integer value when value > 0 -> "positive integer: " + i;
+ default -> "other integer: " + i;
+ }
+ );
+ return proceed(i);
+ }
+}
+
+class Shape {}
+class Rectangle extends Shape {}
+class Circle extends Shape {
+ private final double radius;
+ public Circle(double radius) { this.radius = radius; }
+ double calculateArea() { return Math.PI * radius * radius; }
+}
+
+sealed interface S permits A, B, C {}
+final class A implements S {}
+final class B implements S {}
+record C(int i) implements S {} // Implicitly final
+
+class Application {
+ public static void main(String[] args) {
+ doSomethingWithObject(null);
+ doSomethingWithObject(123);
+ doSomethingWithObject(999L);
+ doSomethingWithObject(12.34);
+ doSomethingWithObject("foo");
+ doSomethingWithObject(List.of(123, "foo", 999L, 12.34));
+
+ doSomethingWithShape(new Rectangle());
+ doSomethingWithShape(new Circle(5));
+ doSomethingWithShape(new Circle(6));
+
+ doSomethingWithSealedClass(new A());
+ doSomethingWithSealedClass(new B());
+ doSomethingWithSealedClass(new C(5));
+
+ doSomethingWithInteger(-1);
+ doSomethingWithInteger(0);
+ doSomethingWithInteger(42);
+ doSomethingWithInteger(-99);
+ doSomethingWithInteger(Integer.valueOf(123));
+ doSomethingWithInteger(null);
+ }
+
+ public static Object doSomethingWithObject(Object o) { return o; }
+ public static void doSomethingWithSealedClass(S s) {}
+ public static void doSomethingWithShape(Shape s) {}
+ public static Object doSomethingWithInteger(Integer o) { return o; }
+}
diff --git a/tests/features1919/java19/SwitchPatternPreview3Error1.java b/tests/features1919/java19/SwitchPatternPreview3Error1.java
new file mode 100644
index 000000000..5f3895cc3
--- /dev/null
+++ b/tests/features1919/java19/SwitchPatternPreview3Error1.java
@@ -0,0 +1,13 @@
+/**
+ * Inspired by examples in https://openjdk.java.net/jeps/420
+ */
+public class SwitchPatternPreview3Error1 {
+ static void constantLabelsMustAppearBeforePatterns1(Integer i) {
+ switch (i) {
+ case null -> System.out.println("value unavailable: " + i);
+ case Integer value when value > 0 -> System.out.println("positive integer: " + i);
+ case -1, 1 -> System.out.println("absolute value 1: " + i);
+ default -> System.out.println("other integer: " + i);
+ }
+ }
+}
diff --git a/tests/features1919/java19/SwitchPatternPreview3Error2.java b/tests/features1919/java19/SwitchPatternPreview3Error2.java
new file mode 100644
index 000000000..c02c4d3cc
--- /dev/null
+++ b/tests/features1919/java19/SwitchPatternPreview3Error2.java
@@ -0,0 +1,21 @@
+/**
+ * Inspired by examples in https://openjdk.java.net/jeps/420
+ */
+public class SwitchPatternPreview3Error2 {
+ static void constantLabelsMustAppearBeforePatterns2(Object o) {
+ switch (o) {
+ case null -> System.out.println("value unavailable: " + o);
+ // This seems to be a bug in JEP 420 implementation. Those constants should be compatible with 'Object'.
+ // case -1, 1 -> System.out.println("absolute value 1: " + o);
+ // case "hello" -> System.out.println("string value: " + o);
+
+ // 'Integer value' dominates the next two, more specific ones -> error
+ case Integer value -> System.out.println("other integer: " + o);
+ case Integer value when (value == 1 || value == -1) -> System.out.println("absolute value 1: " + o);
+ case Integer value when value > 0 -> System.out.println("positive integer: " + o);
+
+ case String value when value.startsWith("hello") -> System.out.println("greeting: " + o);
+ default -> System.out.println("other type: " + o);
+ }
+ }
+}
diff --git a/tests/features1919/java19/SwitchPatternPreview3OK.java b/tests/features1919/java19/SwitchPatternPreview3OK.java
new file mode 100644
index 000000000..7060ec0c2
--- /dev/null
+++ b/tests/features1919/java19/SwitchPatternPreview3OK.java
@@ -0,0 +1,172 @@
+import java.util.List;
+import java.util.Locale;
+
+/**
+ * Inspired by examples in https://openjdk.org/jeps/427
+ */
+public class SwitchPatternPreview3OK {
+ public static void main(String[] args) {
+
+ System.out.println(formatterPatternSwitch(null));
+ System.out.println(formatterPatternSwitch(123));
+ System.out.println(formatterPatternSwitch(999L));
+ System.out.println(formatterPatternSwitch(12.34));
+ System.out.println(formatterPatternSwitch("foo"));
+ System.out.println(formatterPatternSwitch(List.of(123, "foo", 999L, 12.34)));
+
+ System.out.println(testCircle(new Rectangle()));
+ System.out.println(testCircle(new Circle(5)));
+ System.out.println(testCircle(new Circle(6)));
+
+ System.out.println(testSealedCoverage(new A()));
+ System.out.println(testSealedCoverage(new B()));
+ System.out.println(testSealedCoverage(new C(5)));
+
+// constantLabelMustAppearBeforePattern(-1);
+// constantLabelMustAppearBeforePattern(0);
+// constantLabelMustAppearBeforePattern(42);
+// constantLabelMustAppearBeforePattern(-99);
+// constantLabelMustAppearBeforePattern(Integer.valueOf(123));
+// constantLabelMustAppearBeforePattern(null);
+
+ constantLabelMustAppearBeforePatternInteger(-1);
+ constantLabelMustAppearBeforePatternInteger(0);
+ constantLabelMustAppearBeforePatternInteger(42);
+ constantLabelMustAppearBeforePatternInteger(-99);
+ constantLabelMustAppearBeforePatternInteger(Integer.valueOf(123));
+ constantLabelMustAppearBeforePatternInteger(null);
+
+// System.out.println(testGenericSealedExhaustive(new B<Integer>()));
+ }
+
+ static String formatterPatternSwitch(Object o) {
+ return switch (o) {
+ case null -> "null";
+ case Integer i -> String.format("int %d", i);
+ case Long l -> String.format("long %d", l);
+ case Double d -> String.format(Locale.ENGLISH, "double %f", d);
+ case String s -> String.format("String %s", s);
+ default -> o.toString();
+ };
+ }
+
+ static class Shape {}
+ static class Rectangle extends Shape {}
+ static class Circle extends Shape {
+ private final double radius;
+ public Circle(double radius) { this.radius = radius; }
+ double calculateArea() { return Math.PI * radius * radius; }
+ }
+
+ static String testCircle(Shape s) {
+ return switch (s) {
+ case Circle c when (c.calculateArea() > 100) -> "Large circle";
+ case Circle c -> "Small circle";
+ default -> "Non-circle";
+ };
+ }
+
+ sealed interface S permits A, B, C {}
+ final static class A implements S {}
+ final static class B implements S {}
+ static record C(int i) implements S {} // Implicitly final
+
+ static String testSealedCoverage(S s) {
+ return switch (s) {
+ case A a -> "Sealed sub-class A";
+ case B b -> "Sealed sub-class B";
+ case C c -> "Sealed sub-record C";
+ };
+ }
+
+ /**
+ * According to an example from JEP 420, this should work, but it does not, neither with Javac nor ECJ.
+ *
+ * See:
+ * https://openjdk.java.net/jeps/420#1b--Dominance-of-pattern-labels
+ * https://bugs.openjdk.java.net/browse/JDK-8273326
+ * https://bugs.eclipse.org/bugs/show_bug.cgi?id=579355
+ *
+ * TODO: reactivate when implemented or move to preview 3 with Java 19, Eclipse 4.24.
+ */
+ /*
+ static String constantLabelMustAppearBeforePattern(Object o) {
+ switch (o) {
+ case null -> System.out.println("value unavailable: " + i);
+ case -1, 1 -> System.out.println("special case:" + o);
+ case Integer i && i > 0 -> System.out.println("positive integer: " + o);
+ case Integer i -> System.out.println("other integer: " + o);
+ default -> System.out.println("non-integer: " + o);
+ }
+ return i == null ? "null" : i.toString();
+ }
+ */
+
+ static String constantLabelMustAppearBeforePatternInteger(Integer i) {
+ switch (i) {
+ case null -> System.out.println("value unavailable: " + i);
+ case -1, 1 -> System.out.println("absolute value 1: " + i);
+ case Integer value when value > 0 -> System.out.println("positive integer: " + i);
+ default -> System.out.println("other integer: " + i);
+ }
+ return i == null ? "null" : i.toString();
+ }
+
+ static void nullCanAppearAfterConstantLabel(Integer i) {
+ switch (i) {
+ case -1, 1 -> System.out.println("absolute value 1: " + i);
+ case null -> System.out.println("value unavailable: " + i);
+ case Integer value when value > 0 -> System.out.println("positive integer: " + i);
+ default -> System.out.println("other integer: " + i);
+ }
+ }
+
+ static void defaultCanAppearBeforePattern(Integer i) {
+ switch (i) {
+ case null -> System.out.println("value unavailable: " + i);
+ case -1, 1 -> System.out.println("absolute value 1: " + i);
+ default -> System.out.println("other integer: " + i);
+ case Integer value when value > 0 -> System.out.println("positive integer: " + i);
+ }
+ }
+
+ static void defaultCanAppearBeforeNull(Integer i) {
+ switch (i) {
+ case -1, 1 -> System.out.println("absolute value 1: " + i);
+ default -> System.out.println("other integer: " + i);
+ case null -> System.out.println("value unavailable: " + i);
+ case Integer value when value > 0 -> System.out.println("positive integer: " + i);
+ }
+ }
+
+ static void defaultCanAppearBeforeConstantLabel(Integer i) {
+ switch (i) {
+ case null -> System.out.println("value unavailable: " + i);
+ default -> System.out.println("other integer: " + i);
+ case -1, 1 -> System.out.println("absolute value 1: " + i);
+ case Integer value when value > 0 -> System.out.println("positive integer: " + i);
+ }
+ }
+
+ /**
+ * According to an example from JEP 420, this should work, and it does with Javac, but not with ECJ.
+ *
+ * See:
+ * https://openjdk.java.net/jeps/420#2--Exhaustiveness-of-switch-expressions-and-statements
+ * https://bugs.eclipse.org/bugs/show_bug.cgi?id=579360
+ *
+ * TODO: reactivate when implemented or move to preview 3 with Java 19, Eclipse 4.24.
+ */
+ /*
+ sealed interface I<T> permits A, B {}
+ final static class A<X> implements I<String> {}
+ final static class B<Y> implements I<Y> {}
+
+ static int testGenericSealedExhaustive(I<Integer> i) {
+ return switch (i) {
+ // Exhaustive as no A case possible!
+ case B<Integer> bi -> 42;
+ };
+ }
+ */
+}