aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCK <karsten_knuth@gmx.net>2023-12-07 14:38:12 -0800
committergoogle-java-format Team <google-java-format-dev+copybara@google.com>2023-12-07 14:38:45 -0800
commitb86c508be5f42e7ed0d55cd1abe2c04d2db66676 (patch)
treedcbc4fda1b5ebb93f2b80a15e1cf5948328a89d4
parentad771541474eebceb2c6666cb61d4836bf6d8560 (diff)
downloadgoogle-java-format-b86c508be5f42e7ed0d55cd1abe2c04d2db66676.tar.gz
Add support for guard clauses in Java 21 switch expressions
This PR adds support for `switch` statements where a `case` has a guard clause. See Issue #983 Fixes #988 COPYBARA_INTEGRATE_REVIEW=https://github.com/google/google-java-format/pull/988 from TheCK:master 4771486db7d8aab84eb4ecf8e68af2612d0c2b5c PiperOrigin-RevId: 588913297
-rw-r--r--core/pom.xml29
-rw-r--r--core/src/main/java/com/google/googlejavaformat/java/Formatter.java30
-rw-r--r--core/src/main/java/com/google/googlejavaformat/java/java17/Java17InputAstVisitor.java14
-rw-r--r--core/src/main/java/com/google/googlejavaformat/java/java21/Java21InputAstVisitor.java36
-rw-r--r--core/src/test/java/com/google/googlejavaformat/java/FormatterIntegrationTest.java1
-rw-r--r--core/src/test/resources/com/google/googlejavaformat/java/testdata/SwitchGuardClause.input9
-rw-r--r--core/src/test/resources/com/google/googlejavaformat/java/testdata/SwitchGuardClause.output9
7 files changed, 117 insertions, 11 deletions
diff --git a/core/pom.xml b/core/pom.xml
index 038e4ed..d1363fe 100644
--- a/core/pom.xml
+++ b/core/pom.xml
@@ -226,7 +226,7 @@
<profile>
<id>jdk11</id>
<activation>
- <jdk>(,17)</jdk>
+ <jdk>[11,17)</jdk>
</activation>
<build>
<plugins>
@@ -236,6 +236,7 @@
<configuration>
<excludes>
<exclude>**/Java17InputAstVisitor.java</exclude>
+ <exclude>**/Java21InputAstVisitor.java</exclude>
</excludes>
</configuration>
</plugin>
@@ -243,6 +244,32 @@
<artifactId>maven-javadoc-plugin</artifactId>
<configuration>
<excludePackageNames>com.google.googlejavaformat.java.java17</excludePackageNames>
+ <excludePackageNames>com.google.googlejavaformat.java.java21</excludePackageNames>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
+ <profile>
+ <id>jdk17</id>
+ <activation>
+ <jdk>[17,21)</jdk>
+ </activation>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <configuration>
+ <excludes>
+ <exclude>**/Java21InputAstVisitor.java</exclude>
+ </excludes>
+ </configuration>
+ </plugin>
+ <plugin>
+ <artifactId>maven-javadoc-plugin</artifactId>
+ <configuration>
+ <excludePackageNames>com.google.googlejavaformat.java.java21</excludePackageNames>
</configuration>
</plugin>
</plugins>
diff --git a/core/src/main/java/com/google/googlejavaformat/java/Formatter.java b/core/src/main/java/com/google/googlejavaformat/java/Formatter.java
index 9ff702d..5aa7a12 100644
--- a/core/src/main/java/com/google/googlejavaformat/java/Formatter.java
+++ b/core/src/main/java/com/google/googlejavaformat/java/Formatter.java
@@ -151,16 +151,14 @@ public final class Formatter {
OpsBuilder builder = new OpsBuilder(javaInput, javaOutput);
// Output the compilation unit.
JavaInputAstVisitor visitor;
- if (Runtime.version().feature() >= 17) {
- try {
- visitor =
- Class.forName("com.google.googlejavaformat.java.java17.Java17InputAstVisitor")
- .asSubclass(JavaInputAstVisitor.class)
- .getConstructor(OpsBuilder.class, int.class)
- .newInstance(builder, options.indentationMultiplier());
- } catch (ReflectiveOperationException e) {
- throw new LinkageError(e.getMessage(), e);
- }
+ if (Runtime.version().feature() >= 21) {
+ visitor =
+ createVisitor(
+ "com.google.googlejavaformat.java.java21.Java21InputAstVisitor", builder, options);
+ } else if (Runtime.version().feature() >= 17) {
+ visitor =
+ createVisitor(
+ "com.google.googlejavaformat.java.java17.Java17InputAstVisitor", builder, options);
} else {
visitor = new JavaInputAstVisitor(builder, options.indentationMultiplier());
}
@@ -173,6 +171,18 @@ public final class Formatter {
javaOutput.flush();
}
+ 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/core/src/main/java/com/google/googlejavaformat/java/java17/Java17InputAstVisitor.java b/core/src/main/java/com/google/googlejavaformat/java/java17/Java17InputAstVisitor.java
index a0561e2..97bb2ff 100644
--- a/core/src/main/java/com/google/googlejavaformat/java/java17/Java17InputAstVisitor.java
+++ b/core/src/main/java/com/google/googlejavaformat/java/java17/Java17InputAstVisitor.java
@@ -29,6 +29,7 @@ import com.sun.source.tree.CaseLabelTree;
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.ModifiersTree;
import com.sun.source.tree.ModuleTree;
@@ -238,6 +239,15 @@ public class Java17InputAstVisitor extends JavaInputAstVisitor {
}
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(":");
@@ -267,4 +277,8 @@ public class Java17InputAstVisitor extends JavaInputAstVisitor {
}
return null;
}
+
+ protected ExpressionTree getGuard(final CaseTree node) {
+ return null;
+ }
}
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 0000000..a96ef99
--- /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/core/src/test/java/com/google/googlejavaformat/java/FormatterIntegrationTest.java b/core/src/test/java/com/google/googlejavaformat/java/FormatterIntegrationTest.java
index 61a4346..688b24d 100644
--- a/core/src/test/java/com/google/googlejavaformat/java/FormatterIntegrationTest.java
+++ b/core/src/test/java/com/google/googlejavaformat/java/FormatterIntegrationTest.java
@@ -52,6 +52,7 @@ public class FormatterIntegrationTest {
.putAll(15, "I603")
.putAll(16, "I588")
.putAll(17, "I683", "I684", "I696")
+ .putAll(21, "SwitchGuardClause")
.build();
@Parameters(name = "{index}: {0}")
diff --git a/core/src/test/resources/com/google/googlejavaformat/java/testdata/SwitchGuardClause.input b/core/src/test/resources/com/google/googlejavaformat/java/testdata/SwitchGuardClause.input
new file mode 100644
index 0000000..25df580
--- /dev/null
+++ b/core/src/test/resources/com/google/googlejavaformat/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/core/src/test/resources/com/google/googlejavaformat/java/testdata/SwitchGuardClause.output b/core/src/test/resources/com/google/googlejavaformat/java/testdata/SwitchGuardClause.output
new file mode 100644
index 0000000..25df580
--- /dev/null
+++ b/core/src/test/resources/com/google/googlejavaformat/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;
+ };
+ }
+}