[java] Remove version 21-preview

This commit is contained in:
Andreas Dangel 2024-07-11 12:16:24 +02:00
parent f13e886757
commit 10681cd6a8
No known key found for this signature in database
GPG Key ID: 93450DF2DF9A3FA3
18 changed files with 3 additions and 1903 deletions

View File

@ -19,7 +19,6 @@ Usually the latest non-preview Java Version is the default version.
| 23 (default) | | 7.5.0 |
| 22-preview | | 7.0.0 |
| 22 | | 7.0.0 |
| 21-preview | | 7.0.0 |
| 21 | | 7.0.0 |
| 20 | | 6.55.0 |
| 19 | | 6.48.0 |

View File

@ -51,7 +51,7 @@ class BinaryDistributionIT extends AbstractBinaryDistributionTest {
"java-11", "java-12", "java-13", "java-14", "java-15",
"java-16", "java-17", "java-18", "java-19",
"java-20",
"java-21", "java-21-preview",
"java-21",
"java-22", "java-22-preview",
"java-23", "java-23-preview",
"java-5", "java-6", "java-7",

View File

@ -43,7 +43,6 @@ public class JavaLanguageModule extends LanguageModuleBase implements PmdCapable
.addVersion("19")
.addVersion("20")
.addVersion("21")
.addVersion("21-preview")
.addVersion("22")
.addVersion("22-preview")
.addDefaultVersion("23") // 23 is the default

View File

@ -135,7 +135,7 @@ public final class ASTVariableId extends AbstractTypedSymbolDeclarator<JVariable
* identifier.
*/
public boolean isUnnamed() {
return "_".equals(name) && getLanguageVersion().compareToVersion("21-preview") >= 0;
return "_".equals(name) && getLanguageVersion().compareToVersion("21") >= 0;
}
/** Returns the name of the variable. */

View File

@ -38,7 +38,6 @@ class LanguageVersionTest extends AbstractLanguageVersionTest {
new TestDescriptor(java, "19"),
new TestDescriptor(java, "20"),
new TestDescriptor(java, "21"),
new TestDescriptor(java, "21-preview"),
new TestDescriptor(java, "22"),
new TestDescriptor(java, "22-preview"),
new TestDescriptor(java, "23"),

View File

@ -17,7 +17,6 @@ import org.junit.platform.suite.api.Suite;
Java16TreeDumpTest.class,
Java17TreeDumpTest.class,
Java21TreeDumpTest.class,
Java21PreviewTreeDumpTest.class,
Java22TreeDumpTest.class,
Java22PreviewTreeDumpTest.class
})

View File

@ -1,101 +0,0 @@
/*
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
*/
package net.sourceforge.pmd.lang.java.ast;
import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
import org.junit.jupiter.api.Test;
import net.sourceforge.pmd.lang.ast.ParseException;
import net.sourceforge.pmd.lang.java.BaseJavaTreeDumpTest;
import net.sourceforge.pmd.lang.java.JavaParsingHelper;
import net.sourceforge.pmd.lang.java.symbols.JClassSymbol;
import net.sourceforge.pmd.lang.java.types.JTypeMirror;
import net.sourceforge.pmd.lang.test.ast.BaseParsingHelper;
class Java21PreviewTreeDumpTest extends BaseJavaTreeDumpTest {
private final JavaParsingHelper java21p =
JavaParsingHelper.DEFAULT.withDefaultVersion("21-preview")
.withResourceContext(Java21PreviewTreeDumpTest.class, "jdkversiontests/java21p/");
private final JavaParsingHelper java21 = java21p.withDefaultVersion("21");
@Override
public BaseParsingHelper<?, ?> getParser() {
return java21p;
}
@Test
void templateProcessors() {
doTest("Jep430_StringTemplates");
}
@Test
void templateProcessorsBeforeJava21Preview() {
ParseException thrown = assertThrows(ParseException.class, () -> java21.parseResource("Jep430_StringTemplates.java"));
assertTrue(thrown.getMessage().contains("String templates is a preview feature of JDK 21, you should select your language version accordingly"));
}
@Test
void templateExpressionType() {
ASTCompilationUnit unit = java21p.parse("class Foo {{ int i = 1; String s = STR.\"i = \\{i}\"; }}");
ASTTemplateExpression templateExpression = unit.descendants(ASTTemplateExpression.class).first();
JTypeMirror typeMirror = templateExpression.getTypeMirror();
assertEquals("java.lang.String", ((JClassSymbol) typeMirror.getSymbol()).getCanonicalName());
}
@Test
void unnamedPatternsAndVariables() {
doTest("Jep443_UnnamedPatternsAndVariables");
}
@Test
void unnamedPatternsAndVariablesBeforeJava21Preview() {
ParseException thrown = assertThrows(ParseException.class, () -> java21.parseResource("Jep443_UnnamedPatternsAndVariables.java"));
assertThat(thrown.getMessage(), containsString("Unnamed variables and patterns was only standardized in Java 22, you should select your language version accordingly"));
}
@Test
void unnamedClasses1() {
doTest("Jep445_UnnamedClasses1");
ASTCompilationUnit compilationUnit = java21p.parseResource("Jep445_UnnamedClasses1.java");
assertTrue(compilationUnit.isUnnamedClass());
ASTMethodCall methodCall = compilationUnit.descendants(ASTMethodCall.class).first();
assertNotNull(methodCall.getTypeMirror());
}
@Test
void unnamedClasses2() {
doTest("Jep445_UnnamedClasses2");
}
@Test
void unnamedClasses3() {
doTest("Jep445_UnnamedClasses3");
}
@Test
void unnamedClassesBeforeJava21Preview() {
ParseException thrown = assertThrows(ParseException.class, () -> java21.parseResource("Jep445_UnnamedClasses1.java"));
assertThat(thrown.getMessage(), containsString("Unnamed classes is a preview feature of JDK 21, you should select your language version accordingly"));
}
@Test
void testOrdinaryCompilationUnit() {
ASTCompilationUnit compilationUnit = java21.parse("public class Foo { public static void main(String[] args) {}}");
assertFalse(compilationUnit.isUnnamedClass());
}
@Test
void testModularCompilationUnit() {
ASTCompilationUnit compilationUnit = java21.parse("module foo {}");
assertFalse(compilationUnit.isUnnamedClass());
}
}

View File

@ -35,7 +35,7 @@ enum class JavaVersion : Comparable<JavaVersion> {
J18,
J19,
J20,
J21, J21__PREVIEW,
J21,
J22, J22__PREVIEW,
J23, J23__PREVIEW;

View File

@ -1,193 +0,0 @@
/*
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
*/
import static java.lang.StringTemplate.RAW;
import static java.util.FormatProcessor.FMT;
import java.io.File;
import java.time.format.DateTimeFormatter;
import java.time.LocalTime;
/**
* @see <a href="https://openjdk.org/jeps/430">JEP 430: String Templates (Preview)</a>
*/
class Jep430_StringTemplates {
record Request(String date, String time, String ipAddress) {}
static void STRTemplateProcessor() {
// Embedded expressions can be strings
String firstName = "Bill";
String lastName = "Duck";
String fullName = STR."\{firstName} \{lastName}";
// | "Bill Duck"
String sortName = STR."\{lastName}, \{firstName}";
// | "Duck, Bill"
// Embedded expressions can perform arithmetic
int x = 10, y = 20;
String s1 = STR."\{x} + \{y} = \{x + y}";
// | "10 + 20 = 30"
// Embedded expressions can invoke methods and access fields
String s2 = STR."You have a \{getOfferType()} waiting for you!";
// | "You have a gift waiting for you!"
Request req = new Request("2022-03-25", "15:34", "8.8.8.8");
String t = STR."Access at \{req.date} \{req.time} from \{req.ipAddress}";
//| "Access at 2022-03-25 15:34 from 8.8.8.8"
String filePath = "tmp.dat";
File file = new File(filePath);
String old = "The file " + filePath + " " + (file.exists() ? "does" : "does not") + " exist";
String msg = STR."The file \{filePath} \{file.exists() ? "does" : "does not"} exist";
// | "The file tmp.dat does exist" or "The file tmp.dat does not exist"
// spread over multiple lines
String time = STR."The time is \{
// The java.time.format package is very useful
DateTimeFormatter
.ofPattern("HH:mm:ss")
.format(LocalTime.now())
} right now";
// | "The time is 12:34:56 right now"
// Left to right
// Embedded expressions can be postfix increment expressions
int index = 0;
String data = STR."\{index++}, \{index++}, \{index++}, \{index++}";
// | "0, 1, 2, 3"
// Embedded expression is a (nested) template expression
String[] fruit = { "apples", "oranges", "peaches" };
String s3 = STR."\{fruit[0]}, \{STR."\{fruit[1]}, \{fruit[2]}"}";
// | "apples, oranges, peaches"
String s4 = STR."\{fruit[0]}, \{
STR."\{fruit[1]}, \{fruit[2]}"
}";
}
static String getOfferType() { return "_getOfferType_"; }
static void multilineTemplateExpressions() {
String title = "My Web Page";
String text = "Hello, world";
String html = STR."""
<html>
<head>
<title>\{title}</title>
</head>
<body>
<p>\{text}</p>
</body>
</html>
""";
/*
| """
| <html>
| <head>
| <title>My Web Page</title>
| </head>
| <body>
| <p>Hello, world</p>
| </body>
| </html>
| """
*/
String name = "Joan Smith";
String phone = "555-123-4567";
String address = "1 Maple Drive, Anytown";
String json = STR."""
{
"name": "\{name}",
"phone": "\{phone}",
"address": "\{address}"
}
""";
/*
| """
| {
| "name": "Joan Smith",
| "phone": "555-123-4567",
| "address": "1 Maple Drive, Anytown"
| }
| """
*/
record Rectangle(String name, double width, double height) {
double area() {
return width * height;
}
}
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 = STR."""
Description Width Height Area
\{zone[0].name} \{zone[0].width} \{zone[0].height} \{zone[0].area()}
\{zone[1].name} \{zone[1].width} \{zone[1].height} \{zone[1].area()}
\{zone[2].name} \{zone[2].width} \{zone[2].height} \{zone[2].area()}
Total \{zone[0].area() + zone[1].area() + zone[2].area()}
""";
/*
| """
| Description Width Height Area
| Alfa 17.8 31.4 558.92
| Bravo 9.6 12.4 119.03999999999999
| Charlie 7.1 11.23 79.733
| Total 757.693
| """
*/
}
static void FMTTemplateProcessor() {
record Rectangle(String name, double width, double height) {
double area() {
return width * height;
}
};
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()}
""";
/*
| """
| Description Width Height Area
| Alfa 17.80 31.40 558.92
| Bravo 9.60 12.40 119.04
| Charlie 7.10 11.23 79.73
| Total 757.69
| """
*/
}
static void ensuringSafety() {
String name = "Joan";
StringTemplate st = RAW."My name is \{name}";
String info = STR.process(st);
}
record User(String firstName, int accountNumber) {}
static void literalsInsideTemplateExpressions() {
String s1 = STR."Welcome to your account";
// | "Welcome to your account"
User user = new User("Lisa", 12345);
String s2 = STR."Welcome, \{user.firstName()}, to your account \{user.accountNumber()}";
// | "Welcome, Lisa, to your account 12345"
}
static void emptyEmbeddedExpression() {
String s1=STR."Test \{ }";
}
}

View File

@ -1,123 +0,0 @@
/*
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
*/
import java.util.ArrayDeque;
import java.util.List;
import java.util.Queue;
import java.util.stream.Collectors;
/**
* @see <a href="https://openjdk.org/jeps/443">JEP 443: Unnamed Patterns and Variables (Preview)</a>
*/
class Jep443_UnamedPatternsAndVariables {
record Point(int x, int y) { }
enum Color { RED, GREEN, BLUE }
record ColoredPoint(Point p, Color c) { }
void unnamedPatterns1() {
ColoredPoint r = new ColoredPoint(new Point(3,4), Color.GREEN);
if (r instanceof ColoredPoint(Point p, Color _)) {
System.out.println(p.x() + " " + p.y());
}
if (r instanceof ColoredPoint(Point(int x, int y), _)) {
System.out.println(x + " " + y);
}
}
sealed abstract class Ball permits RedBall, BlueBall, GreenBall { }
final class RedBall extends Ball { }
final class BlueBall extends Ball { }
final class GreenBall extends Ball { }
record Box<T extends Ball>(T content) { }
void unnamedPatterns2() {
Box<? extends Ball> b = new Box<>(new RedBall());
switch (b) {
case Box(RedBall _) -> processBox(b);
case Box(BlueBall _) -> processBox(b);
case Box(GreenBall _) -> stopProcessing();
}
switch (b) {
case Box(RedBall _), Box(BlueBall _) -> processBox(b);
case Box(GreenBall _) -> stopProcessing();
case Box(_) -> pickAnotherBox();
}
int x = 42;
switch (b) {
// multiple patterns guarded by one guard
case Box(RedBall _), Box(BlueBall _) when x == 42 -> processBox(b);
case Box(_) -> pickAnotherBox();
}
}
private void processBox(Box<? extends Ball> b) {}
private void stopProcessing() {}
private void pickAnotherBox() {}
class Order {}
private static final int LIMIT = 10;
private int sideEffect() {
return 0;
}
void unnamedVariables(List<Order> orders) {
int total = 0;
for (Order _ : orders) {
if (total < LIMIT) {
total++;
}
}
System.out.println("total: " + total);
for (int i = 0, _ = sideEffect(); i < 10; i++) {
System.out.println(i);
}
Queue<Integer> q = new ArrayDeque<>(); // x1, y1, z1, x2, y2, z2 ..
while (q.size() >= 3) {
int x = q.remove();
int y = q.remove();
int _ = q.remove(); // z is unused
Point p = new Point(x, y);
}
while (q.size() >= 3) {
var x = q.remove();
var _ = q.remove();
var _ = q.remove();
Point p = new Point(x, 0);
}
}
static class ScopedContext implements AutoCloseable {
@Override
public void close() { }
public static ScopedContext acquire() {
return new ScopedContext();
}
}
void unusedVariables2() {
try (var _ = ScopedContext.acquire()) {
//... acquiredContext not used ...
}
String s = "123";
try {
int i = Integer.parseInt(s);
System.out.println(i);
} catch (NumberFormatException _) {
System.out.println("Bad number: " + s);
} catch (Exception _) {
System.out.println("error...");
}
List.of("a", "b").stream().collect(Collectors.toMap(String::toUpperCase, _ -> "NO_DATA"));
}
}

View File

@ -1,13 +0,0 @@
/*
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
*/
/**
* @see <a href="https://openjdk.org/jeps/445">JEP 445: Unnamed Classes and Instance Main Methods (Preview)</a>
*/
void main() {
System.out.println("Hello World");
}

View File

@ -1,13 +0,0 @@
+- CompilationUnit[@PackageName = ""]
+- MethodDeclaration[@Abstract = false, @Arity = 0, @EffectiveVisibility = Visibility.V_PACKAGE, @Final = false, @MainMethod = true, @Name = "main", @Overridden = false, @Static = false, @Varargs = false, @Visibility = Visibility.V_PACKAGE, @Void = true]
+- ModifierList[@EffectiveModifiers = (), @ExplicitModifiers = ()]
+- VoidType[]
+- FormalParameters[@Empty = true, @Size = 0]
+- Block[@Empty = false, @Size = 1, @containsComment = false]
+- ExpressionStatement[]
+- MethodCall[@CompileTimeConstant = false, @Image = "println", @MethodName = "println", @ParenthesisDepth = 0, @Parenthesized = false]
+- FieldAccess[@AccessType = AccessType.READ, @CompileTimeConstant = false, @Image = "out", @Name = "out", @ParenthesisDepth = 0, @Parenthesized = false]
| +- TypeExpression[@CompileTimeConstant = false, @ParenthesisDepth = 0, @Parenthesized = false]
| +- ClassType[@FullyQualified = false, @PackageQualifier = null, @SimpleName = "System"]
+- ArgumentList[@Empty = false, @Size = 1]
+- StringLiteral[@CompileTimeConstant = true, @ConstValue = "Hello World", @Empty = false, @Image = "\"Hello World\"", @Length = 11, @LiteralText = "\"Hello World\"", @ParenthesisDepth = 0, @Parenthesized = false, @TextBlock = false]

View File

@ -1,15 +0,0 @@
/*
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
*/
/**
* @see <a href="https://openjdk.org/jeps/445">JEP 445: Unnamed Classes and Instance Main Methods (Preview)</a>
*/
String greeting() { return "Hello, World!"; }
void main() {
System.out.println(greeting());
}

View File

@ -1,21 +0,0 @@
+- CompilationUnit[@PackageName = ""]
+- MethodDeclaration[@Abstract = false, @Arity = 0, @EffectiveVisibility = Visibility.V_PACKAGE, @Final = false, @Name = "greeting", @Overridden = false, @Static = false, @Varargs = false, @Visibility = Visibility.V_PACKAGE, @Void = false]
| +- ModifierList[@EffectiveModifiers = (), @ExplicitModifiers = ()]
| +- ClassType[@FullyQualified = false, @PackageQualifier = null, @SimpleName = "String"]
| +- FormalParameters[@Empty = true, @Size = 0]
| +- Block[@Empty = false, @Size = 1, @containsComment = false]
| +- ReturnStatement[]
| +- StringLiteral[@CompileTimeConstant = true, @ConstValue = "Hello, World!", @Empty = false, @Image = "\"Hello, World!\"", @Length = 13, @LiteralText = "\"Hello, World!\"", @ParenthesisDepth = 0, @Parenthesized = false, @TextBlock = false]
+- MethodDeclaration[@Abstract = false, @Arity = 0, @EffectiveVisibility = Visibility.V_PACKAGE, @Final = false, @MainMethod = true, @Name = "main", @Overridden = false, @Static = false, @Varargs = false, @Visibility = Visibility.V_PACKAGE, @Void = true]
+- ModifierList[@EffectiveModifiers = (), @ExplicitModifiers = ()]
+- VoidType[]
+- FormalParameters[@Empty = true, @Size = 0]
+- Block[@Empty = false, @Size = 1, @containsComment = false]
+- ExpressionStatement[]
+- MethodCall[@CompileTimeConstant = false, @Image = "println", @MethodName = "println", @ParenthesisDepth = 0, @Parenthesized = false]
+- FieldAccess[@AccessType = AccessType.READ, @CompileTimeConstant = false, @Image = "out", @Name = "out", @ParenthesisDepth = 0, @Parenthesized = false]
| +- TypeExpression[@CompileTimeConstant = false, @ParenthesisDepth = 0, @Parenthesized = false]
| +- ClassType[@FullyQualified = false, @PackageQualifier = null, @SimpleName = "System"]
+- ArgumentList[@Empty = false, @Size = 1]
+- MethodCall[@CompileTimeConstant = false, @Image = "greeting", @MethodName = "greeting", @ParenthesisDepth = 0, @Parenthesized = false]
+- ArgumentList[@Empty = true, @Size = 0]

View File

@ -1,15 +0,0 @@
/*
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
*/
/**
* @see <a href="https://openjdk.org/jeps/445">JEP 445: Unnamed Classes and Instance Main Methods (Preview)</a>
*/
String greeting = "Hello, World!";
void main() {
System.out.println(greeting);
}

View File

@ -1,19 +0,0 @@
+- CompilationUnit[@PackageName = ""]
+- FieldDeclaration[@EffectiveVisibility = Visibility.V_PACKAGE, @Static = false, @Visibility = Visibility.V_PACKAGE]
| +- ModifierList[@EffectiveModifiers = (), @ExplicitModifiers = ()]
| +- ClassType[@FullyQualified = false, @PackageQualifier = null, @SimpleName = "String"]
| +- VariableDeclarator[@Initializer = true, @Name = "greeting"]
| +- VariableId[@ArrayType = false, @EffectiveVisibility = Visibility.V_PACKAGE, @EnumConstant = false, @ExceptionBlockParameter = false, @Field = true, @Final = false, @ForLoopVariable = false, @ForeachVariable = false, @FormalParameter = false, @LambdaParameter = false, @LocalVariable = false, @Name = "greeting", @PatternBinding = false, @RecordComponent = false, @ResourceDeclaration = false, @Static = false, @TypeInferred = false, @Unnamed = false, @Visibility = Visibility.V_PACKAGE]
| +- StringLiteral[@CompileTimeConstant = true, @ConstValue = "Hello, World!", @Empty = false, @Image = "\"Hello, World!\"", @Length = 13, @LiteralText = "\"Hello, World!\"", @ParenthesisDepth = 0, @Parenthesized = false, @TextBlock = false]
+- MethodDeclaration[@Abstract = false, @Arity = 0, @EffectiveVisibility = Visibility.V_PACKAGE, @Final = false, @MainMethod = true, @Name = "main", @Overridden = false, @Static = false, @Varargs = false, @Visibility = Visibility.V_PACKAGE, @Void = true]
+- ModifierList[@EffectiveModifiers = (), @ExplicitModifiers = ()]
+- VoidType[]
+- FormalParameters[@Empty = true, @Size = 0]
+- Block[@Empty = false, @Size = 1, @containsComment = false]
+- ExpressionStatement[]
+- MethodCall[@CompileTimeConstant = false, @Image = "println", @MethodName = "println", @ParenthesisDepth = 0, @Parenthesized = false]
+- FieldAccess[@AccessType = AccessType.READ, @CompileTimeConstant = false, @Image = "out", @Name = "out", @ParenthesisDepth = 0, @Parenthesized = false]
| +- TypeExpression[@CompileTimeConstant = false, @ParenthesisDepth = 0, @Parenthesized = false]
| +- ClassType[@FullyQualified = false, @PackageQualifier = null, @SimpleName = "System"]
+- ArgumentList[@Empty = false, @Size = 1]
+- VariableAccess[@AccessType = AccessType.READ, @CompileTimeConstant = false, @Image = "greeting", @Name = "greeting", @ParenthesisDepth = 0, @Parenthesized = false]