From 40f0eedf888e8cca1218903bdfe59c3f47ad89bc Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Thu, 13 Aug 2020 19:58:21 +0200 Subject: [PATCH] [java] Text Blocks are now a permanent language feature with JDK 15 --- pmd-java/etc/grammar/Java.jjt | 11 +- .../pmd/lang/java/ast/Java15Test.java | 74 +++++++++++ .../jdkversiontests/java15/TextBlocks.java | 115 ++++++++++++++++++ 3 files changed, 195 insertions(+), 5 deletions(-) create mode 100644 pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/Java15Test.java create mode 100644 pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java15/TextBlocks.java diff --git a/pmd-java/etc/grammar/Java.jjt b/pmd-java/etc/grammar/Java.jjt index 3e00f639ea..cb8559352b 100644 --- a/pmd-java/etc/grammar/Java.jjt +++ b/pmd-java/etc/grammar/Java.jjt @@ -1,5 +1,6 @@ /** - * Remove support for Java 13 preview language features + * Remove support for Java 13 preview language features. + * Promote text blocks as a permanent language features with Java 15. * Andreas Dangel 08/2020 *==================================================================== * Add support for record types introduced as a preview language @@ -453,14 +454,14 @@ public class JavaParser { } private void checkForTextBlockLiteral() { - if (jdkVersion != 14 || !preview) { - throwParseException("Text block literals are only supported with Java 14 Preview"); + if (jdkVersion < 15 && !preview) { + throwParseException("Text block literals are only supported with Java 14 Preview and Java >= 15"); } } private void checkForNewStringSpaceEscape(String s) { - if ((jdkVersion != 14 || !preview) && s.contains("\\s") && !s.contains("\\\\s")) { - throwParseException("The escape sequence \"\\s\" is only supported with Java 14 Preview"); + if ((jdkVersion < 15 && !preview) && s.contains("\\s") && !s.contains("\\\\s")) { + throwParseException("The escape sequence \"\\s\" is only supported with Java 14 Preview and Java >= 15"); } } diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/Java15Test.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/Java15Test.java new file mode 100644 index 0000000000..003c5072cc --- /dev/null +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/Java15Test.java @@ -0,0 +1,74 @@ +/* + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package net.sourceforge.pmd.lang.java.ast; + +import java.util.ArrayList; +import java.util.List; + +import org.junit.Assert; +import org.junit.Test; + +import net.sourceforge.pmd.lang.ast.ParseException; +import net.sourceforge.pmd.lang.java.JavaParsingHelper; + +public class Java15Test { + private final JavaParsingHelper java15 = + JavaParsingHelper.WITH_PROCESSING.withDefaultVersion("15") + .withResourceContext(Java15Test.class, "jdkversiontests/java15/"); + private final JavaParsingHelper java15p = java15.withDefaultVersion("15-preview"); + private final JavaParsingHelper java14 = java15.withDefaultVersion("14"); + + @Test + public void textBlocks() { + textBlocks(java15); + textBlocks(java15p); + } + + private void textBlocks(JavaParsingHelper parser) { + ASTCompilationUnit compilationUnit = parser.parseResource("TextBlocks.java"); + List literals = compilationUnit.findDescendantsOfType(ASTLiteral.class); + Assert.assertEquals(22, literals.size()); + Assert.assertFalse(literals.get(2).isTextBlock()); + Assert.assertFalse(literals.get(12).isTextBlock()); + Assert.assertFalse(literals.get(17).isTextBlock()); + Assert.assertFalse(literals.get(18).isTextBlock()); + Assert.assertFalse(literals.get(20).isTextBlock()); + Assert.assertFalse(literals.get(21).isTextBlock()); + + List textBlocks = new ArrayList<>(); + for (ASTLiteral literal : literals) { + if (literal.isTextBlock()) { + textBlocks.add(literal); + } + } + Assert.assertEquals(16, textBlocks.size()); + Assert.assertEquals("\"\"\"\n" + + " \n" + + " \n" + + "

Hello, world

\n" + + " \n" + + " \n" + + " \"\"\"", + textBlocks.get(0).getImage()); + Assert.assertEquals("\n" + + " \n" + + "

Hello, world

\n" + + " \n" + + "\n", textBlocks.get(0).getTextBlockContent()); + + // Note: More tests are in ASTLiteralTest. + } + + @Test(expected = ParseException.class) + public void textBlocksBeforeJava15ShouldFail() { + java14.parseResource("TextBlocks.java"); + } + + @Test(expected = ParseException.class) + public void stringEscapeSequenceShouldFail() { + java14.parse("class Foo { String s =\"a\\sb\"; }"); + } + +} diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java15/TextBlocks.java b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java15/TextBlocks.java new file mode 100644 index 0000000000..ab7eba0ccf --- /dev/null +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/ast/jdkversiontests/java15/TextBlocks.java @@ -0,0 +1,115 @@ +import javax.script.ScriptEngine; +import javax.script.ScriptEngineManager; + +/** + * Text Blocks are a permanent language feature with JDK 15. + * + * @see + +

Hello, world

+ + + """; + System.out.println(html); + + String query = """ + SELECT `EMP_ID`, `LAST_NAME` FROM `EMPLOYEE_TB` + WHERE `CITY` = 'INDIANAPOLIS' + ORDER BY `EMP_ID`, `LAST_NAME`; + """; + System.out.println(query); + + ScriptEngine engine = new ScriptEngineManager().getEngineByName("js"); + Object obj = engine.eval(""" + function hello() { + print('"Hello, world"'); + } + + hello(); + """); + + // Escape sequences + String htmlWithEscapes = """ + \r + \r +

Hello, world

\r + \r + \r + """; + System.out.println(htmlWithEscapes); + + String season = """ + winter"""; // the six characters w i n t e r + + String period = """ + winter + """; // the seven characters w i n t e r LF + + String greeting = + """ + Hi, "Bob" + """; // the ten characters H i , SP " B o b " LF + + String salutation = + """ + Hi, + "Bob" + """; // the eleven characters H i , LF SP " B o b " LF + + String empty = """ + """; // the empty string (zero length) + + String quote = """ + " + """; // the two characters " LF + + String backslash = """ + \\ + """; // the two characters \ LF + + String normalStringLiteral = "test"; + + String code = + """ + String text = \""" + A text block inside a text block + \"""; + """; + + // new escape sequences + String text = """ + Lorem ipsum dolor sit amet, consectetur adipiscing \ + elit, sed do eiusmod tempor incididunt ut labore \ + et dolore magna aliqua.\ + """; + System.out.println(text); + + String colors = """ + red \s + green\s + blue \s + """; + System.out.println(colors); + + // empty new line as first content + String emptyLine = """ + +test +"""; + System.out.println(emptyLine.replaceAll("\n", "")); + + // backslash escapes + String bs = """ + \\test + """; + System.out.println(bs.replaceAll("\n", "")); + } +}