From 6be5a0a6a62e9afefad53a27f4c75d95ae7dac74 Mon Sep 17 00:00:00 2001 From: Alexander Kriegisch Date: Sun, 10 Dec 2023 13:53:15 +0700 Subject: [PATCH] Add tests for Java 21 string patterns TODO: Due to eclipse-jdt/eclipse.jdt.core#1719, one line per test is currently rendered incorrectly. After the upstream fix, change "\Bill \Duck" to "Bill Duck". Signed-off-by: Alexander Kriegisch --- .../java21/StringPatternsPreview1.java | 114 +++++++++++++++++ .../java21/StringPatternsPreview1Aspect.aj | 118 ++++++++++++++++++ .../ajc1921/Java21PreviewFeaturesTests.java | 8 +- .../aspectj/systemtest/ajc1921/ajc1921.xml | 71 +++++++++++ 4 files changed, 309 insertions(+), 2 deletions(-) create mode 100644 tests/features1921/java21/StringPatternsPreview1.java create mode 100644 tests/features1921/java21/StringPatternsPreview1Aspect.aj diff --git a/tests/features1921/java21/StringPatternsPreview1.java b/tests/features1921/java21/StringPatternsPreview1.java new file mode 100644 index 000000000..ae1829c84 --- /dev/null +++ b/tests/features1921/java21/StringPatternsPreview1.java @@ -0,0 +1,114 @@ +import java.io.File; +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.LocalTime; +import java.time.format.DateTimeFormatter; + +import static java.lang.StringTemplate.RAW; +import static java.util.FormatProcessor.FMT; + +/** + * Examples taken from JEP 430 + */ +public class StringPatternsPreview1 { + public static void main(String[] args) { + // Embedded expressions can be strings + String firstName = "Bill", lastName = "Duck"; + // TODO: Due to https://github.com/eclipse-jdt/eclipse.jdt.core/issues/1719, this is currently rendered incorrectly + System.out.println(STR."\{firstName} \{lastName}"); + + // Embedded expressions can perform arithmetic + int x = 10, y = 20; + System.out.println(STR."\{x} + \{y} = \{x + y}"); + + // Embedded expressions can invoke methods and access fields + System.out.println(STR."You have a \{getOfferType()} waiting for you!"); + Request req = new Request(); + System.out.println(STR."Access at \{req.date} \{req.time} from \{req.ipAddress}"); + + // Embedded expressions can use double quotes without escaping them + String filePath = "_dummy.dat"; + File file = new File(filePath); + System.out.println(STR."The file \{filePath} \{file.exists() ? "does" : "does not"} exist"); + + // Embedded expressions can span multiple lines + System.out.println( + STR."The time is \{ + DateTimeFormatter + .ofPattern("HH:mm:ss") + .format(LocalTime.of(11, 11, 11)) + } or roughly eleven after eleven" + ); + + // Embedded expressions can be nested + String[] fruit = { "apples", "oranges", "peaches" }; + System.out.println(STR."\{fruit[0]}, \{STR."\{fruit[1]}, \{fruit[2]}"}\n"); + + // Embedded expressions can be used in multi-line strings + String title = "My Web Page"; + String text = "Hello, world"; + String html = STR.""" + + + \{title} + + +

\{text}

+ + + """; + System.out.println(html); + + // The FMT template processor interprets format specifiers which appear to the left of embedded expressions. + // The format specifiers are the same as those defined in java.util.Formatter. + Rectangle[] zone = new Rectangle[] { + new Rectangle("Alfa", 17.8, 31.4), + new Rectangle("Bravo", 9.6, 12.4), + new Rectangle("Charlie", 7.1, 11.23), + }; + String table = FMT.""" + Description Width Height Area + %-12s\{zone[0].name} %7.2f\{zone[0].width} %7.2f\{zone[0].height} %7.2f\{zone[0].area()} + %-12s\{zone[1].name} %7.2f\{zone[1].width} %7.2f\{zone[1].height} %7.2f\{zone[1].area()} + %-12s\{zone[2].name} %7.2f\{zone[2].width} %7.2f\{zone[2].height} %7.2f\{zone[2].area()} + \{" ".repeat(28)} Total %7.2f\{zone[0].area() + zone[1].area() + zone[2].area()} + """; + System.out.println(table); + + // Built-in security: Each template expression needs to pass through a processor. + String name = "Joan"; + StringTemplate stringTemplate = RAW."My name is \{name}"; + String processedTemplate = STR.process(stringTemplate); + System.out.println(processedTemplate); + } + + static Object getOfferType() { + return "special New Year's sale discount"; + } + + static class Request { + LocalDate date; + LocalTime time; + InetAddress ipAddress; + + Request() { + LocalDateTime dateTime = LocalDateTime.of(2011, 11, 11, 11, 11, 11); + date = dateTime.toLocalDate(); + time = dateTime.toLocalTime(); + try { + // localhost/127.0.0.1 + ipAddress = InetAddress.getByAddress("localhost", new byte[] { 127, 0, 0, 1 }); + } catch (UnknownHostException e) { + throw new RuntimeException(e); + } + } + } + + record Rectangle(String name, double width, double height) { + double area() { + return width * height; + } + } +} diff --git a/tests/features1921/java21/StringPatternsPreview1Aspect.aj b/tests/features1921/java21/StringPatternsPreview1Aspect.aj new file mode 100644 index 000000000..1f9a3ce9f --- /dev/null +++ b/tests/features1921/java21/StringPatternsPreview1Aspect.aj @@ -0,0 +1,118 @@ +import java.io.File; +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.LocalTime; +import java.time.format.DateTimeFormatter; + +import static java.lang.StringTemplate.RAW; +import static java.util.FormatProcessor.FMT; + +/** + * Examples taken from JEP 430 + */ +public aspect StringPatternsPreview1Aspect { + public static void main(String[] args) {} + + before() : execution(* main(String[])) { + System.out.println(thisJoinPoint); + + // Embedded expressions can be strings + String firstName = "Bill", lastName = "Duck"; + // TODO: Due to https://github.com/eclipse-jdt/eclipse.jdt.core/issues/1719, this is currently rendered incorrectly + System.out.println(STR."\{firstName} \{lastName}"); + + // Embedded expressions can perform arithmetic + int x = 10, y = 20; + System.out.println(STR."\{x} + \{y} = \{x + y}"); + + // Embedded expressions can invoke methods and access fields + System.out.println(STR."You have a \{getOfferType()} waiting for you!"); + Request req = new Request(); + System.out.println(STR."Access at \{req.date} \{req.time} from \{req.ipAddress}"); + + // Embedded expressions can use double quotes without escaping them + String filePath = "_dummy.dat"; + File file = new File(filePath); + System.out.println(STR."The file \{filePath} \{file.exists() ? "does" : "does not"} exist"); + + // Embedded expressions can span multiple lines + System.out.println( + STR."The time is \{ + DateTimeFormatter + .ofPattern("HH:mm:ss") + .format(LocalTime.of(11, 11, 11)) + } or roughly eleven after eleven" + ); + + // Embedded expressions can be nested + String[] fruit = { "apples", "oranges", "peaches" }; + System.out.println(STR."\{fruit[0]}, \{STR."\{fruit[1]}, \{fruit[2]}"}\n"); + + // Embedded expressions can be used in multi-line strings + String title = "My Web Page"; + String text = "Hello, world"; + String html = STR.""" + + + \{title} + + +

\{text}

+ + + """; + System.out.println(html); + + // The FMT template processor interprets format specifiers which appear to the left of embedded expressions. + // The format specifiers are the same as those defined in java.util.Formatter. + Rectangle[] zone = new Rectangle[] { + new Rectangle("Alfa", 17.8, 31.4), + new Rectangle("Bravo", 9.6, 12.4), + new Rectangle("Charlie", 7.1, 11.23), + }; + String table = FMT.""" + Description Width Height Area + %-12s\{zone[0].name} %7.2f\{zone[0].width} %7.2f\{zone[0].height} %7.2f\{zone[0].area()} + %-12s\{zone[1].name} %7.2f\{zone[1].width} %7.2f\{zone[1].height} %7.2f\{zone[1].area()} + %-12s\{zone[2].name} %7.2f\{zone[2].width} %7.2f\{zone[2].height} %7.2f\{zone[2].area()} + \{" ".repeat(28)} Total %7.2f\{zone[0].area() + zone[1].area() + zone[2].area()} + """; + System.out.println(table); + + // Built-in security: Each template expression needs to pass through a processor. + String name = "Joan"; + StringTemplate stringTemplate = RAW."My name is \{name}"; + String processedTemplate = STR.process(stringTemplate); + System.out.println(processedTemplate); + } + + static Object getOfferType() { + return "special New Year's sale discount"; + } + + static class Request { + LocalDate date; + LocalTime time; + InetAddress ipAddress; + + Request() { + LocalDateTime dateTime = LocalDateTime.of(2011, 11, 11, 11, 11, 11); + date = dateTime.toLocalDate(); + time = dateTime.toLocalTime(); + try { + // localhost/127.0.0.1 + ipAddress = InetAddress.getByAddress("localhost", new byte[] { 127, 0, 0, 1 }); + } catch (UnknownHostException e) { + throw new RuntimeException(e); + } + } + } + + record Rectangle(String name, double width, double height) { + double area() { + return width * height; + } + } +} diff --git a/tests/src/test/java/org/aspectj/systemtest/ajc1921/Java21PreviewFeaturesTests.java b/tests/src/test/java/org/aspectj/systemtest/ajc1921/Java21PreviewFeaturesTests.java index 4b4de845d..5ef087602 100644 --- a/tests/src/test/java/org/aspectj/systemtest/ajc1921/Java21PreviewFeaturesTests.java +++ b/tests/src/test/java/org/aspectj/systemtest/ajc1921/Java21PreviewFeaturesTests.java @@ -16,8 +16,12 @@ import org.aspectj.testing.XMLBasedAjcTestCaseForJava21Only; */ public class Java21PreviewFeaturesTests extends XMLBasedAjcTestCaseForJava21Only { - public void testDummyPreviewJava21() { - //runTest("dummy preview Java 21"); + public void testStringPatterns() { + runTest("string patterns"); + } + + public void testStringPatternsAspect() { + runTest("string patterns aspect"); } public static Test suite() { diff --git a/tests/src/test/resources/org/aspectj/systemtest/ajc1921/ajc1921.xml b/tests/src/test/resources/org/aspectj/systemtest/ajc1921/ajc1921.xml index 42a58da0c..a7b5d0d95 100644 --- a/tests/src/test/resources/org/aspectj/systemtest/ajc1921/ajc1921.xml +++ b/tests/src/test/resources/org/aspectj/systemtest/ajc1921/ajc1921.xml @@ -188,4 +188,75 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- 2.39.5