diff --git a/build.gradle b/build.gradle index 6cb66587..b5dfe4a5 100644 --- a/build.gradle +++ b/build.gradle @@ -97,6 +97,6 @@ jdks { } javaVersions { - libraryTarget = 17 + libraryTarget = 21 runtime = 21 } diff --git a/core/src/main/java/com/google/googlejavaformat/java/java21/Java21InputAstVisitor.java b/core/src/main/java/com/google/googlejavaformat/java/java21/Java21InputAstVisitor.java new file mode 100644 index 00000000..a96ef99e --- /dev/null +++ b/core/src/main/java/com/google/googlejavaformat/java/java21/Java21InputAstVisitor.java @@ -0,0 +1,36 @@ +/* + * Copyright 2023 The google-java-format Authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing permissions and limitations under + * the License. + */ + +package com.google.googlejavaformat.java.java21; + +import com.google.googlejavaformat.OpsBuilder; +import com.google.googlejavaformat.java.java17.Java17InputAstVisitor; +import com.sun.source.tree.CaseTree; +import com.sun.source.tree.ExpressionTree; + +/** + * Extends {@link Java17InputAstVisitor} with support for AST nodes that were added or modified in + * Java 21. + */ +public class Java21InputAstVisitor extends Java17InputAstVisitor { + + public Java21InputAstVisitor(OpsBuilder builder, int indentMultiplier) { + super(builder, indentMultiplier); + } + + @Override + protected ExpressionTree getGuard(final CaseTree node) { + return node.getGuard(); + } +} diff --git a/palantir-java-format/src/main/java/com/palantir/javaformat/java/Formatter.java b/palantir-java-format/src/main/java/com/palantir/javaformat/java/Formatter.java index bf07ca2d..7d74a80f 100644 --- a/palantir-java-format/src/main/java/com/palantir/javaformat/java/Formatter.java +++ b/palantir-java-format/src/main/java/com/palantir/javaformat/java/Formatter.java @@ -131,15 +131,10 @@ static JavaOutput format( OpsBuilder opsBuilder = new OpsBuilder(javaInput); JavaInputAstVisitor visitor; - if (getRuntimeVersion() >= 14) { - try { - visitor = Class.forName("com.palantir.javaformat.java.java14.Java14InputAstVisitor") - .asSubclass(JavaInputAstVisitor.class) - .getConstructor(OpsBuilder.class, int.class) - .newInstance(opsBuilder, options.indentationMultiplier()); - } catch (ReflectiveOperationException e) { - throw new RuntimeException(e.getMessage(), e); - } + if (getRuntimeVersion() >= 21) { + visitor = createVisitor("com.palantir.javaformat.java.java21.Java21InputAstVisitor", opsBuilder, options); + } else if (getRuntimeVersion() >= 14) { + visitor = createVisitor("com.palantir.javaformat.java.java14.Java14InputAstVisitor", opsBuilder, options); } else { visitor = new JavaInputAstVisitor(opsBuilder, options.indentationMultiplier()); } @@ -206,6 +201,18 @@ static int getRuntimeVersion() { return Runtime.version().feature(); } + private static JavaInputAstVisitor createVisitor( + final String className, final OpsBuilder builder, final JavaFormatterOptions options) { + try { + return Class.forName(className) + .asSubclass(JavaInputAstVisitor.class) + .getConstructor(OpsBuilder.class, int.class) + .newInstance(builder, options.indentationMultiplier()); + } catch (ReflectiveOperationException e) { + throw new LinkageError(e.getMessage(), e); + } + } + static boolean errorDiagnostic(Diagnostic input) { if (input.getKind() != Diagnostic.Kind.ERROR) { return false; diff --git a/palantir-java-format/src/main/java/com/palantir/javaformat/java/java14/Java14InputAstVisitor.java b/palantir-java-format/src/main/java/com/palantir/javaformat/java/java14/Java14InputAstVisitor.java index d2ebe1d7..4e66d264 100644 --- a/palantir-java-format/src/main/java/com/palantir/javaformat/java/java14/Java14InputAstVisitor.java +++ b/palantir-java-format/src/main/java/com/palantir/javaformat/java/java14/Java14InputAstVisitor.java @@ -31,6 +31,7 @@ import com.sun.source.tree.CaseTree; import com.sun.source.tree.ClassTree; import com.sun.source.tree.CompilationUnitTree; +import com.sun.source.tree.ExpressionTree; import com.sun.source.tree.InstanceOfTree; import com.sun.source.tree.LambdaExpressionTree; import com.sun.source.tree.ModifiersTree; @@ -275,6 +276,15 @@ public Void visitCase(CaseTree node, Void unused) { } builder.close(); } + + final ExpressionTree guard = getGuard(node); + if (guard != null) { + builder.space(); + token("when"); + builder.space(); + scan(guard, null); + } + switch (node.getCaseKind()) { case STATEMENT: token(":"); @@ -341,4 +351,8 @@ private static Object invoke(Method m, Object target) { throw new RuntimeException(e.getMessage(), e); } } + + protected ExpressionTree getGuard(final CaseTree node) { + return null; + } } diff --git a/palantir-java-format/src/main/java/com/palantir/javaformat/java/java21/Java21InputAstVisitor.java b/palantir-java-format/src/main/java/com/palantir/javaformat/java/java21/Java21InputAstVisitor.java new file mode 100644 index 00000000..b727d84d --- /dev/null +++ b/palantir-java-format/src/main/java/com/palantir/javaformat/java/java21/Java21InputAstVisitor.java @@ -0,0 +1,36 @@ +/* + * (c) Copyright 2024 Palantir Technologies Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.palantir.javaformat.java.java21; + +import com.palantir.javaformat.OpsBuilder; +import com.palantir.javaformat.java.java14.Java14InputAstVisitor; +import com.sun.source.tree.CaseTree; +import com.sun.source.tree.ExpressionTree; +/** + * Extends {@link Java14InputAstVisitor} with support for AST nodes that were added or modified in + * Java 21. + */ +public class Java21InputAstVisitor extends Java14InputAstVisitor { + public Java21InputAstVisitor(OpsBuilder builder, int indentMultiplier) { + super(builder, indentMultiplier); + } + + @Override + protected ExpressionTree getGuard(final CaseTree node) { + return node.getGuard(); + } +} \ No newline at end of file diff --git a/palantir-java-format/src/test/java/com/palantir/javaformat/java/FileBasedTests.java b/palantir-java-format/src/test/java/com/palantir/javaformat/java/FileBasedTests.java index cf8b6af3..4f4000e7 100644 --- a/palantir-java-format/src/test/java/com/palantir/javaformat/java/FileBasedTests.java +++ b/palantir-java-format/src/test/java/com/palantir/javaformat/java/FileBasedTests.java @@ -50,6 +50,7 @@ public final class FileBasedTests { .putAll(15, "I603") .putAll(16, "I588") .putAll(17, "I683", "I684", "I696") + .putAll(21, "SwitchGuardClause") .build(); private final Class testClass; diff --git a/palantir-java-format/src/test/resources/com/palantir/javaformat/java/testdata/SwitchGuardClause.input b/palantir-java-format/src/test/resources/com/palantir/javaformat/java/testdata/SwitchGuardClause.input new file mode 100644 index 00000000..25df5809 --- /dev/null +++ b/palantir-java-format/src/test/resources/com/palantir/javaformat/java/testdata/SwitchGuardClause.input @@ -0,0 +1,9 @@ +class SwitchGuardClause { + boolean test(Object x) { + return switch (x) { + case String s when s.length() < 5 -> true; + case Integer i -> false; + default -> true; + }; + } +} diff --git a/palantir-java-format/src/test/resources/com/palantir/javaformat/java/testdata/SwitchGuardClause.output b/palantir-java-format/src/test/resources/com/palantir/javaformat/java/testdata/SwitchGuardClause.output new file mode 100644 index 00000000..f4219572 --- /dev/null +++ b/palantir-java-format/src/test/resources/com/palantir/javaformat/java/testdata/SwitchGuardClause.output @@ -0,0 +1,9 @@ +class SwitchGuardClause { + boolean test(Object x) { + return switch (x) { + case String s when s.length() < 5 -> true; + case Integer i -> false; + default -> true; + }; + } +}