From 53aca1d95c51ca66818fefd28ed90150d7f2f2af Mon Sep 17 00:00:00 2001 From: Mateusz Matela Date: Thu, 25 Jan 2024 20:39:00 +0100 Subject: [PATCH] Java formatter setting for switch arror opening brace position (#1473) --- .../formatter/FormatterRegressionTests.java | 25 ++++++++ .../workspace/Formatter/testGH1473/A_out.java | 58 +++++++++++++++++ .../workspace/Formatter/testGH1473/B_out.java | 57 +++++++++++++++++ .../workspace/Formatter/testGH1473/C_out.java | 62 +++++++++++++++++++ .../workspace/Formatter/testGH1473/in.java | 53 ++++++++++++++++ .../DefaultCodeFormatterConstants.java | 19 +++++- .../DefaultCodeFormatterOptions.java | 6 ++ .../formatter/LineBreaksPreparator.java | 19 ++++-- 8 files changed, 291 insertions(+), 8 deletions(-) create mode 100644 org.eclipse.jdt.core.tests.model/workspace/Formatter/testGH1473/A_out.java create mode 100644 org.eclipse.jdt.core.tests.model/workspace/Formatter/testGH1473/B_out.java create mode 100644 org.eclipse.jdt.core.tests.model/workspace/Formatter/testGH1473/C_out.java create mode 100644 org.eclipse.jdt.core.tests.model/workspace/Formatter/testGH1473/in.java diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/formatter/FormatterRegressionTests.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/formatter/FormatterRegressionTests.java index 7046a5e5042..53df77fa9e1 100644 --- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/formatter/FormatterRegressionTests.java +++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/formatter/FormatterRegressionTests.java @@ -16329,4 +16329,29 @@ void foo(int i) { } """); } + +/** + * https://github.com/eclipse-jdt/eclipse.jdt/issues/1473 - Java formatter setting for switch arror opening brace position + */ +public void testGH1473a() throws JavaModelException { + setComplianceLevel(CompilerOptions.VERSION_14); + this.formatterPrefs.brace_position_for_block_in_case = DefaultCodeFormatterConstants.NEXT_LINE; + this.formatterPrefs.brace_position_for_block_in_case_after_arrow = DefaultCodeFormatterConstants.END_OF_LINE; + String input = getCompilationUnit("Formatter", "", "testGH1473", "in.java").getSource(); + formatSource(input, getCompilationUnit("Formatter", "", "testGH1473", "A_out.java").getSource()); +} +public void testGH1473b() throws JavaModelException { + setComplianceLevel(CompilerOptions.VERSION_14); + this.formatterPrefs.brace_position_for_block_in_case = DefaultCodeFormatterConstants.END_OF_LINE; + this.formatterPrefs.brace_position_for_block_in_case_after_arrow = DefaultCodeFormatterConstants.NEXT_LINE; + String input = getCompilationUnit("Formatter", "", "testGH1473", "in.java").getSource(); + formatSource(input, getCompilationUnit("Formatter", "", "testGH1473", "B_out.java").getSource()); +} +public void testGH1473c() throws JavaModelException { + setComplianceLevel(CompilerOptions.VERSION_14); + this.formatterPrefs.brace_position_for_block_in_case = DefaultCodeFormatterConstants.NEXT_LINE_SHIFTED; + this.formatterPrefs.brace_position_for_block_in_case_after_arrow = DefaultCodeFormatterConstants.NEXT_LINE_SHIFTED; + String input = getCompilationUnit("Formatter", "", "testGH1473", "in.java").getSource(); + formatSource(input, getCompilationUnit("Formatter", "", "testGH1473", "C_out.java").getSource()); +} } diff --git a/org.eclipse.jdt.core.tests.model/workspace/Formatter/testGH1473/A_out.java b/org.eclipse.jdt.core.tests.model/workspace/Formatter/testGH1473/A_out.java new file mode 100644 index 00000000000..544ca351fa3 --- /dev/null +++ b/org.eclipse.jdt.core.tests.model/workspace/Formatter/testGH1473/A_out.java @@ -0,0 +1,58 @@ +class Test { + void foo(int i) { + int k = switch (i) { + case 1, 2, 3: + { + yield 33; + } + case 4: + yield 44; + case 5: + { + } + yield 55; + default: + { + throw new RuntimeException(); + } + }; + + switch (k) { + case 1, 2, 3: + { + k += 4; + } { + k += 55; + break; + } + case 4: + k += 43; + break; + default: + { + throw new RuntimeException(); + } + } + + int m = switch (i) { + case 1, 2, 3 -> { + k++; + yield 33; + } + case 4 -> 66; + default -> { + throw new RuntimeException(); + } + }; + + switch (m) { + case 1, 2, 3 -> { + k += 4; + } + case 4 -> k += 55; + default -> { + throw new RuntimeException(); + } + } + } +} \ No newline at end of file diff --git a/org.eclipse.jdt.core.tests.model/workspace/Formatter/testGH1473/B_out.java b/org.eclipse.jdt.core.tests.model/workspace/Formatter/testGH1473/B_out.java new file mode 100644 index 00000000000..97522a6cae0 --- /dev/null +++ b/org.eclipse.jdt.core.tests.model/workspace/Formatter/testGH1473/B_out.java @@ -0,0 +1,57 @@ +class Test { + void foo(int i) { + int k = switch (i) { + case 1, 2, 3: { + yield 33; + } + case 4: + yield 44; + case 5: { + } + yield 55; + default: { + throw new RuntimeException(); + } + }; + + switch (k) { + case 1, 2, 3: { + k += 4; + } { + k += 55; + break; + } + case 4: + k += 43; + break; + default: { + throw new RuntimeException(); + } + } + + int m = switch (i) { + case 1, 2, 3 -> + { + k++; + yield 33; + } + case 4 -> 66; + default -> + { + throw new RuntimeException(); + } + }; + + switch (m) { + case 1, 2, 3 -> + { + k += 4; + } + case 4 -> k += 55; + default -> + { + throw new RuntimeException(); + } + } + } +} \ No newline at end of file diff --git a/org.eclipse.jdt.core.tests.model/workspace/Formatter/testGH1473/C_out.java b/org.eclipse.jdt.core.tests.model/workspace/Formatter/testGH1473/C_out.java new file mode 100644 index 00000000000..6cad3e95244 --- /dev/null +++ b/org.eclipse.jdt.core.tests.model/workspace/Formatter/testGH1473/C_out.java @@ -0,0 +1,62 @@ +class Test { + void foo(int i) { + int k = switch (i) { + case 1, 2, 3: + { + yield 33; + } + case 4: + yield 44; + case 5: + { + } + yield 55; + default: + { + throw new RuntimeException(); + } + }; + + switch (k) { + case 1, 2, 3: + { + k += 4; + } { + k += 55; + break; + } + case 4: + k += 43; + break; + default: + { + throw new RuntimeException(); + } + } + + int m = switch (i) { + case 1, 2, 3 -> + { + k++; + yield 33; + } + case 4 -> 66; + default -> + { + throw new RuntimeException(); + } + }; + + switch (m) { + case 1, 2, 3 -> + { + k += 4; + } + case 4 -> k += 55; + default -> + { + throw new RuntimeException(); + } + } + } +} \ No newline at end of file diff --git a/org.eclipse.jdt.core.tests.model/workspace/Formatter/testGH1473/in.java b/org.eclipse.jdt.core.tests.model/workspace/Formatter/testGH1473/in.java new file mode 100644 index 00000000000..d8c9c301f29 --- /dev/null +++ b/org.eclipse.jdt.core.tests.model/workspace/Formatter/testGH1473/in.java @@ -0,0 +1,53 @@ +class Test { + void foo(int i) { + int k = switch(i) { + case 1,2,3: { + yield 33; + } + case 4: + yield 44; + case 5:{} + yield 55; + default: { + throw new RuntimeException(); + } + }; + + switch(k) { + case 1,2,3: { + k += 4; + } + { + k += 55; + break; + } + case 4: + k += 43; + break; + default: { + throw new RuntimeException(); + } + } + + int m = switch(i) { + case 1,2,3 -> { + k++; + yield 33; + } + case 4 -> 66; + default -> { + throw new RuntimeException(); + } + }; + + switch (m) { + case 1,2,3 -> { + k += 4; + } + case 4 -> k +=55; + default -> { + throw new RuntimeException(); + } + } + } +} \ No newline at end of file diff --git a/org.eclipse.jdt.core/formatter/org/eclipse/jdt/core/formatter/DefaultCodeFormatterConstants.java b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/core/formatter/DefaultCodeFormatterConstants.java index 770d1209abb..477caa8d2ac 100644 --- a/org.eclipse.jdt.core/formatter/org/eclipse/jdt/core/formatter/DefaultCodeFormatterConstants.java +++ b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/core/formatter/DefaultCodeFormatterConstants.java @@ -1053,8 +1053,8 @@ public class DefaultCodeFormatterConstants { public static final String FORMATTER_BRACE_POSITION_FOR_BLOCK = JavaCore.PLUGIN_ID + ".formatter.brace_position_for_block"; //$NON-NLS-1$ /** *
-	 * FORMATTER / Option to position the braces of a block in a case statement when the block is the first statement following
-	 *             the case
+	 * FORMATTER / Option to position the braces of a block in a switch statement/expression when the block
+	 *             is the first statement following a case with colon
 	 *     - option id:         "org.eclipse.jdt.core.formatter.brace_position_for_block_in_case"
 	 *     - possible values:   { END_OF_LINE, NEXT_LINE, NEXT_LINE_SHIFTED, NEXT_LINE_ON_WRAP }
 	 *     - default:           END_OF_LINE
@@ -1066,6 +1066,21 @@ public class DefaultCodeFormatterConstants {
 	 * @since 3.0
 	 */
 	public static final String FORMATTER_BRACE_POSITION_FOR_BLOCK_IN_CASE = JavaCore.PLUGIN_ID + ".formatter.brace_position_for_block_in_case";	//$NON-NLS-1$
+	/**
+	 * 
+	 * FORMATTER / Option to position the braces of a block in a switch statement/expression when the block
+	 *             is the first statement following a case with arrow
+	 *     - option id:         "org.eclipse.jdt.core.formatter.brace_position_for_block_in_case_after_arrow"
+	 *     - possible values:   { END_OF_LINE, NEXT_LINE, NEXT_LINE_SHIFTED, NEXT_LINE_ON_WRAP }
+	 *     - default:           END_OF_LINE
+	 * 
+ * @see #END_OF_LINE + * @see #NEXT_LINE + * @see #NEXT_LINE_SHIFTED + * @see #NEXT_LINE_ON_WRAP + * @since 3.37 + */ + public static final String FORMATTER_BRACE_POSITION_FOR_BLOCK_IN_CASE_AFTER_ARROW = JavaCore.PLUGIN_ID + ".formatter.brace_position_for_block_in_case_after_arrow"; //$NON-NLS-1$ /** *
 	 * FORMATTER / Option to position the braces of a constructor declaration
diff --git a/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/DefaultCodeFormatterOptions.java b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/DefaultCodeFormatterOptions.java
index 14325ad9311..8dda1ac2055 100644
--- a/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/DefaultCodeFormatterOptions.java
+++ b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/DefaultCodeFormatterOptions.java
@@ -186,6 +186,7 @@ public static DefaultCodeFormatterOptions getJavaConventionsSettings() {
 	public String brace_position_for_array_initializer;
 	public String brace_position_for_block;
 	public String brace_position_for_block_in_case;
+	public String brace_position_for_block_in_case_after_arrow;
 	public String brace_position_for_constructor_declaration;
 	public String brace_position_for_enum_constant;
 	public String brace_position_for_enum_declaration;
@@ -637,6 +638,7 @@ public Map getMap() {
 		options.put(DefaultCodeFormatterConstants.FORMATTER_BRACE_POSITION_FOR_ARRAY_INITIALIZER, this.brace_position_for_array_initializer);
 		options.put(DefaultCodeFormatterConstants.FORMATTER_BRACE_POSITION_FOR_BLOCK, this.brace_position_for_block);
 		options.put(DefaultCodeFormatterConstants.FORMATTER_BRACE_POSITION_FOR_BLOCK_IN_CASE, this.brace_position_for_block_in_case);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_BRACE_POSITION_FOR_BLOCK_IN_CASE_AFTER_ARROW, this.brace_position_for_block_in_case_after_arrow);
 		options.put(DefaultCodeFormatterConstants.FORMATTER_BRACE_POSITION_FOR_CONSTRUCTOR_DECLARATION, this.brace_position_for_constructor_declaration);
 		options.put(DefaultCodeFormatterConstants.FORMATTER_BRACE_POSITION_FOR_ENUM_CONSTANT, this.brace_position_for_enum_constant);
 		options.put(DefaultCodeFormatterConstants.FORMATTER_BRACE_POSITION_FOR_ENUM_DECLARATION, this.brace_position_for_enum_declaration);
@@ -1326,6 +1328,8 @@ public void set(Map settings) {
 				this.brace_position_for_block_in_case = DefaultCodeFormatterConstants.END_OF_LINE;
 			}
 		}
+		setString(settings, DefaultCodeFormatterConstants.FORMATTER_BRACE_POSITION_FOR_BLOCK_IN_CASE_AFTER_ARROW, BRACE_POSITION_VALUES,
+				v -> this.brace_position_for_block_in_case_after_arrow = v);
 		final Object bracePositionForConstructorDeclarationOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_BRACE_POSITION_FOR_CONSTRUCTOR_DECLARATION);
 		if (bracePositionForConstructorDeclarationOption != null) {
 			try {
@@ -3035,6 +3039,7 @@ public void setDefaultSettings() {
 		this.brace_position_for_array_initializer = DefaultCodeFormatterConstants.END_OF_LINE;
 		this.brace_position_for_block = DefaultCodeFormatterConstants.END_OF_LINE;
 		this.brace_position_for_block_in_case = DefaultCodeFormatterConstants.END_OF_LINE;
+		this.brace_position_for_block_in_case_after_arrow = DefaultCodeFormatterConstants.END_OF_LINE;
 		this.brace_position_for_constructor_declaration = DefaultCodeFormatterConstants.END_OF_LINE;
 		this.brace_position_for_enum_constant = DefaultCodeFormatterConstants.END_OF_LINE;
 		this.brace_position_for_enum_declaration = DefaultCodeFormatterConstants.END_OF_LINE;
@@ -3439,6 +3444,7 @@ public void setJavaConventionsSettings() {
 		this.brace_position_for_array_initializer = DefaultCodeFormatterConstants.END_OF_LINE;
 		this.brace_position_for_block = DefaultCodeFormatterConstants.END_OF_LINE;
 		this.brace_position_for_block_in_case = DefaultCodeFormatterConstants.END_OF_LINE;
+		this.brace_position_for_block_in_case_after_arrow = DefaultCodeFormatterConstants.END_OF_LINE;
 		this.brace_position_for_constructor_declaration = DefaultCodeFormatterConstants.END_OF_LINE;
 		this.brace_position_for_enum_constant = DefaultCodeFormatterConstants.END_OF_LINE;
 		this.brace_position_for_enum_declaration = DefaultCodeFormatterConstants.END_OF_LINE;
diff --git a/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/LineBreaksPreparator.java b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/LineBreaksPreparator.java
index 956880c8b7c..4abbb026119 100644
--- a/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/LineBreaksPreparator.java
+++ b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/LineBreaksPreparator.java
@@ -302,12 +302,10 @@ public boolean visit(Block node) {
 			return true; // braces have been handled in #visit(MethodDeclaration)
 
 		String bracePosition = this.options.brace_position_for_block;
-		if (parent instanceof SwitchStatement) {
-			List siblings = ((SwitchStatement) parent).statements();
-			int blockPosition = siblings.indexOf(node);
-			boolean isFirstInCase = blockPosition > 0 && (siblings.get(blockPosition - 1) instanceof SwitchCase);
-			if (isFirstInCase)
-				bracePosition = this.options.brace_position_for_block_in_case;
+		if (parent instanceof SwitchStatement sw) {
+			bracePosition = getBracePositionInSwitch(node, sw.statements());
+		} else if (parent instanceof SwitchExpression se) {
+			bracePosition = getBracePositionInSwitch(node, se.statements());
 		} else if (parent instanceof LambdaExpression) {
 			bracePosition = this.options.brace_position_for_lambda_body;
 		}
@@ -323,6 +321,15 @@ public boolean visit(Block node) {
 		return true;
 	}
 
+	private String getBracePositionInSwitch(Block node, List siblings) {
+		int blockPosition = siblings.indexOf(node);
+		if (blockPosition > 0 && siblings.get(blockPosition - 1) instanceof SwitchCase switchCase) {
+			return switchCase.isSwitchLabeledRule() ? this.options.brace_position_for_block_in_case_after_arrow
+					: this.options.brace_position_for_block_in_case;
+		}
+		return this.options.brace_position_for_block;
+	}
+
 	private void blankLinesAroundBlock(ASTNode blockStatement, List siblings) {
 		putBlankLinesBefore(blockStatement, this.options.blank_lines_before_code_block);
 		if (!this.options.put_empty_statement_on_new_line) {