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 97bb2ffe5..6818f4a03 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 @@ -83,6 +83,7 @@ public Void visitBindingPattern(BindingPatternTree node, Void unused) { } private void visitBindingPattern(ModifiersTree modifiers, Tree type, Name name) { + builder.open(plusFour); if (modifiers != null) { List annotations = visitModifiers(modifiers, Direction.HORIZONTAL, Optional.empty()); @@ -90,7 +91,12 @@ private void visitBindingPattern(ModifiersTree modifiers, Tree type, Name name) } scan(type, null); builder.breakOp(" "); - visit(name); + if (name.isEmpty()) { + token("_"); + } else { + visit(name); + } + builder.close(); } @Override @@ -222,6 +228,11 @@ public Void visitCase(CaseTree node, Void unused) { List labels = node.getLabels(); boolean isDefault = labels.size() == 1 && getOnlyElement(labels).getKind().name().equals("DEFAULT_CASE_LABEL"); + builder.open( + node.getCaseKind().equals(CaseTree.CaseKind.RULE) + && !node.getBody().getKind().equals(Tree.Kind.BLOCK) + ? plusFour + : ZERO); if (isDefault) { token("default", plusTwo); } else { @@ -259,8 +270,8 @@ public Void visitCase(CaseTree node, Void unused) { builder.space(); token("-"); token(">"); - builder.space(); if (node.getBody().getKind() == Tree.Kind.BLOCK) { + builder.space(); // Explicit call with {@link CollapseEmptyOrNot.YES} to handle empty case blocks. visitBlock( (BlockTree) node.getBody(), @@ -268,6 +279,7 @@ public Void visitCase(CaseTree node, Void unused) { AllowLeadingBlankLine.NO, AllowTrailingBlankLine.NO); } else { + builder.breakOp(" "); scan(node.getBody(), null); } builder.guessToken(";"); @@ -275,6 +287,7 @@ public Void visitCase(CaseTree node, Void unused) { default: throw new AssertionError(node.getCaseKind()); } + builder.close(); 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 index a96ef99e2..ad936cae4 100644 --- a/core/src/main/java/com/google/googlejavaformat/java/java21/Java21InputAstVisitor.java +++ b/core/src/main/java/com/google/googlejavaformat/java/java21/Java21InputAstVisitor.java @@ -17,7 +17,12 @@ import com.google.googlejavaformat.OpsBuilder; import com.google.googlejavaformat.java.java17.Java17InputAstVisitor; import com.sun.source.tree.CaseTree; +import com.sun.source.tree.ConstantCaseLabelTree; +import com.sun.source.tree.DeconstructionPatternTree; +import com.sun.source.tree.DefaultCaseLabelTree; import com.sun.source.tree.ExpressionTree; +import com.sun.source.tree.PatternCaseLabelTree; +import com.sun.source.tree.PatternTree; /** * Extends {@link Java17InputAstVisitor} with support for AST nodes that were added or modified in @@ -33,4 +38,42 @@ public Java21InputAstVisitor(OpsBuilder builder, int indentMultiplier) { protected ExpressionTree getGuard(final CaseTree node) { return node.getGuard(); } + + @Override + public Void visitDefaultCaseLabel(DefaultCaseLabelTree node, Void unused) { + token("default"); + return null; + } + + @Override + public Void visitPatternCaseLabel(PatternCaseLabelTree node, Void unused) { + scan(node.getPattern(), null); + return null; + } + + @Override + public Void visitConstantCaseLabel(ConstantCaseLabelTree node, Void aVoid) { + scan(node.getConstantExpression(), null); + return null; + } + + @Override + public Void visitDeconstructionPattern(DeconstructionPatternTree node, Void unused) { + scan(node.getDeconstructor(), null); + builder.open(plusFour); + token("("); + builder.breakOp(); + boolean first = true; + for (PatternTree pattern : node.getNestedPatterns()) { + if (!first) { + token(","); + builder.breakOp(" "); + } + first = false; + scan(pattern, null); + } + builder.close(); + token(")"); + return null; + } } 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 688b24d8e..1bb2ab4f4 100644 --- a/core/src/test/java/com/google/googlejavaformat/java/FormatterIntegrationTest.java +++ b/core/src/test/java/com/google/googlejavaformat/java/FormatterIntegrationTest.java @@ -52,7 +52,7 @@ public class FormatterIntegrationTest { .putAll(15, "I603") .putAll(16, "I588") .putAll(17, "I683", "I684", "I696") - .putAll(21, "SwitchGuardClause") + .putAll(21, "SwitchGuardClause", "SwitchRecord", "SwitchDouble", "SwitchUnderscore") .build(); @Parameters(name = "{index}: {0}") @@ -94,7 +94,7 @@ public static Iterable data() throws IOException { String expectedOutput = outputs.get(fileName); Optional version = VERSIONED_TESTS.inverse().get(fileName).stream().collect(toOptional()); - if (version.isPresent() && Runtime.version().feature() < version.get()) { + if (Runtime.version().feature() < version.orElse(Integer.MAX_VALUE)) { continue; } testInputs.add(new Object[] {fileName, input, expectedOutput}); diff --git a/core/src/test/resources/com/google/googlejavaformat/java/testdata/I880.input b/core/src/test/resources/com/google/googlejavaformat/java/testdata/I880.input new file mode 100644 index 000000000..dfc8a4cf5 --- /dev/null +++ b/core/src/test/resources/com/google/googlejavaformat/java/testdata/I880.input @@ -0,0 +1,19 @@ +class I880 { + public String f(int i) { + return switch (i) { + case 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 -> "looooooooooooooooooooooooooooooooooooooooong expression"; + default -> "looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong expression"; + }; + } + + public boolean test(int i) { + return switch (i) { + case 0 -> // zero + false; + case 1 -> "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa".length() + == 0; + default -> // otherwise + true; + }; + } +} \ No newline at end of file diff --git a/core/src/test/resources/com/google/googlejavaformat/java/testdata/I880.output b/core/src/test/resources/com/google/googlejavaformat/java/testdata/I880.output new file mode 100644 index 000000000..f918665f4 --- /dev/null +++ b/core/src/test/resources/com/google/googlejavaformat/java/testdata/I880.output @@ -0,0 +1,21 @@ +class I880 { + public String f(int i) { + return switch (i) { + case 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 -> + "looooooooooooooooooooooooooooooooooooooooong expression"; + default -> + "looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong expression"; + }; + } + + public boolean test(int i) { + return switch (i) { + case 0 -> // zero + false; + case 1 -> + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa".length() == 0; + default -> // otherwise + true; + }; + } +} diff --git a/core/src/test/resources/com/google/googlejavaformat/java/testdata/SwitchDouble.input b/core/src/test/resources/com/google/googlejavaformat/java/testdata/SwitchDouble.input new file mode 100644 index 000000000..54e22a768 --- /dev/null +++ b/core/src/test/resources/com/google/googlejavaformat/java/testdata/SwitchDouble.input @@ -0,0 +1,7 @@ +class SwitchDouble { + void x(Object o) { + switch (o) { + case null, default: + } + } +} diff --git a/core/src/test/resources/com/google/googlejavaformat/java/testdata/SwitchDouble.output b/core/src/test/resources/com/google/googlejavaformat/java/testdata/SwitchDouble.output new file mode 100644 index 000000000..54e22a768 --- /dev/null +++ b/core/src/test/resources/com/google/googlejavaformat/java/testdata/SwitchDouble.output @@ -0,0 +1,7 @@ +class SwitchDouble { + void x(Object o) { + switch (o) { + case null, default: + } + } +} diff --git a/core/src/test/resources/com/google/googlejavaformat/java/testdata/SwitchRecord.input b/core/src/test/resources/com/google/googlejavaformat/java/testdata/SwitchRecord.input new file mode 100644 index 000000000..2f4fb35d9 --- /dev/null +++ b/core/src/test/resources/com/google/googlejavaformat/java/testdata/SwitchRecord.input @@ -0,0 +1,21 @@ +record SwitchRecord(int i) { + int x(Object o) { + return switch (o) { + case SwitchRecord(int i) -> i; + default -> 0; + }; + } + int f(Object o) { + return switch (o) { + case SwitchRecord(int one, int two, int three, int four, int five, int six, int seven, int eight, int nine) -> nine; + default -> 0; + }; + } + int g(Object o) { + return switch (o) { + case SwitchRecord(int one, int two, int three, int four, int five, int six, int seven, int eight, int nine) -> + System.err.println("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat."); + default -> 0; + }; + } +} diff --git a/core/src/test/resources/com/google/googlejavaformat/java/testdata/SwitchRecord.output b/core/src/test/resources/com/google/googlejavaformat/java/testdata/SwitchRecord.output new file mode 100644 index 000000000..89d212f8c --- /dev/null +++ b/core/src/test/resources/com/google/googlejavaformat/java/testdata/SwitchRecord.output @@ -0,0 +1,46 @@ +record SwitchRecord(int i) { + int x(Object o) { + return switch (o) { + case SwitchRecord(int i) -> i; + default -> 0; + }; + } + + int f(Object o) { + return switch (o) { + case SwitchRecord( + int one, + int two, + int three, + int four, + int five, + int six, + int seven, + int eight, + int nine) -> + nine; + default -> 0; + }; + } + + int g(Object o) { + return switch (o) { + case SwitchRecord( + int one, + int two, + int three, + int four, + int five, + int six, + int seven, + int eight, + int nine) -> + System.err.println( + "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor" + + " incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis" + + " nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo" + + " consequat."); + default -> 0; + }; + } +} diff --git a/core/src/test/resources/com/google/googlejavaformat/java/testdata/SwitchUnderscore.input b/core/src/test/resources/com/google/googlejavaformat/java/testdata/SwitchUnderscore.input new file mode 100644 index 000000000..8d611d24a --- /dev/null +++ b/core/src/test/resources/com/google/googlejavaformat/java/testdata/SwitchUnderscore.input @@ -0,0 +1,8 @@ +public class SwitchUnderscore { + void x(Object o) { + switch (o) { + case String _: + default: + } + } +} diff --git a/core/src/test/resources/com/google/googlejavaformat/java/testdata/SwitchUnderscore.output b/core/src/test/resources/com/google/googlejavaformat/java/testdata/SwitchUnderscore.output new file mode 100644 index 000000000..8d611d24a --- /dev/null +++ b/core/src/test/resources/com/google/googlejavaformat/java/testdata/SwitchUnderscore.output @@ -0,0 +1,8 @@ +public class SwitchUnderscore { + void x(Object o) { + switch (o) { + case String _: + default: + } + } +}