Bug 458208 - [formatter] Follow-up bug for comments

Change-Id: Ie6e26a4d13399b27584635d7293c8510e58c7ec2
Signed-off-by: Mateusz Matela <mateusz.matela@gmail.com>
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/RunFormatterTests.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/RunFormatterTests.java
index 122a68e..4382806 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/RunFormatterTests.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/RunFormatterTests.java
@@ -9,6 +9,7 @@
  *     IBM Corporation - initial API and implementation
  *     Jesper S Moller - Contribution for bug 402173
  *                       Contribution for bug 402892
+ *     Mateusz Matela <mateusz.matela@gmail.com> - [formatter] follow up bug for comments - https://bugs.eclipse.org/458208
  *******************************************************************************/
 package org.eclipse.jdt.core.tests;
 
@@ -37,6 +38,7 @@
 		TEST_SUITES.add(FormatterCommentsClearBlankLinesTests.class);
 		TEST_SUITES.add(FormatterJavadocDontIndentTagsTests.class);
 		TEST_SUITES.add(FormatterJavadocDontIndentTagsDescriptionTests.class);
+		TEST_SUITES.add(FormatterOldBugsGistTests.class);
 	}
 
 	public static Class[] getTestClasses() {
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/formatter/FormatterBugs18Tests.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/formatter/FormatterBugs18Tests.java
index f9dcb0a..d7cddc6 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/formatter/FormatterBugs18Tests.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/formatter/FormatterBugs18Tests.java
@@ -7,6 +7,7 @@
  *
  * Contributors:
  *     IBM Corporation - initial API and implementation
+ *     Mateusz Matela <mateusz.matela@gmail.com> - [formatter] follow up bug for comments - https://bugs.eclipse.org/458208
  *******************************************************************************/
 package org.eclipse.jdt.core.tests.formatter;
 
@@ -185,7 +186,7 @@
 			"			// nothing\n" +
 			"			System.out.println(\"\");\n" +
 			"			return \"\";\n" +
-			"		} );\n" +
+			"		});\n" +
 			"	}\n" +
 			"\n" +
 			"	public Function<String, String> testBad() {\n" +
@@ -193,7 +194,7 @@
 			"			// nothing\n" +
 			"			System.out.println(\"\");\n" +
 			"			return \"\";\n" +
-			"		} );\n" +
+			"		});\n" +
 			"	}\n" +
 			"\n" +
 			"	public Function<String, String> foo(Function<String, String> f) {\n" +
@@ -230,7 +231,7 @@
 			"				}\n"+
 			"			}\n"+
 			"\n"+
-			"		} ).start();\n"+
+			"		}).start();\n"+
 			"	}\n"+
 			"}\n";
 
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/formatter/FormatterBugsTests.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/formatter/FormatterBugsTests.java
index 44b9b8b..0659687 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/formatter/FormatterBugsTests.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/formatter/FormatterBugsTests.java
@@ -11,6 +11,7 @@
  *     Robin Stocker - Bug 49619 - [formatting] comment formatter leaves whitespace in comments

  *     Mateusz Matela <mateusz.matela@gmail.com> - [formatter] Formatter does not format Java code correctly, especially when max line width is set - https://bugs.eclipse.org/303519

  *     Mateusz Matela <mateusz.matela@gmail.com> - [formatter] IndexOutOfBoundsException in TokenManager - https://bugs.eclipse.org/462945

+ *     Mateusz Matela <mateusz.matela@gmail.com> - [formatter] follow up bug for comments - https://bugs.eclipse.org/458208

  *******************************************************************************/

 package org.eclipse.jdt.core.tests.formatter;

 

@@ -1372,7 +1373,6 @@
 // see also bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=287462

 public void testBug198074_dup201022() throws JavaModelException {

 	this.formatterPrefs.join_wrapped_lines = false;

-	this.formatterPrefs.wrap_before_binary_operator = false;

 	String source =

 		"public class Test {\n" +

 		"\n" +

@@ -1399,7 +1399,6 @@
 // duplicate bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=213700

 public void testBug198074_dup213700() throws JavaModelException {

 	this.formatterPrefs.join_wrapped_lines = false;

-	this.formatterPrefs.wrap_before_binary_operator = false;

 	String source =

 		"public class Test {\n" +

 		"\n" +

@@ -1906,7 +1905,8 @@
 		"@MessageDriven(mappedName = \"filiality/SchedulerMQService\",\n" + 

 		"		activationConfig = {\n" + 

 		"				@ActivationConfigProperty(propertyName = \"cronTrigger\",\n" + 

-		"						propertyValue = \"0/10 * * * * ?\") })\n" + 

+		"						propertyValue = \"0/10 * * * * ?\")\n" + 

+		"		})\n" + 

 		"@RunAs(\"admin\")\n" + 

 		"@ResourceAdapter(\"quartz-ra.rar\")\n" + 

 		"@TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)\n" + 

@@ -8041,9 +8041,11 @@
 		"public class X07 {\n" + 

 		"\n" + 

 		"	static final long[] jjtoToken = {\n" + 

-		"			0x7fbfecffL, };\n" + 

+		"			0x7fbfecffL,\n" + 

+		"	};\n" + 

 		"	static final long[] jjtoSkip = {\n" + 

-		"			0x400000L, };\n" + 

+		"			0x400000L,\n" + 

+		"	};\n" + 

 		"\n" + 

 		"}\n"

 	);

@@ -8072,10 +8074,12 @@
 		"\n" + 

 		"	static final long[] jjtoToken =\n" + 

 		"	{\n" + 

-		"			0x7fbfecffL, };\n" + 

+		"			0x7fbfecffL,\n" + 

+		"	};\n" + 

 		"	static final long[] jjtoSkip =\n" + 

 		"	{\n" + 

-		"			0x400000L, };\n" +

+		"			0x400000L,\n" +

+		"	};\n" + 

 		"\n" + 

 		"}\n"

 	);

@@ -8124,7 +8128,8 @@
 		"public class X09 {\n" + 

 		"	public Class[] getAdapterList() {\n" + 

 		"		return new Class[] {\n" + 

-		"				IWorkbenchAdapter.class };\n" + 

+		"				IWorkbenchAdapter.class\n" + 

+		"		};\n" + 

 		"	}\n" + 

 		"}\n"

 	);

@@ -8796,7 +8801,6 @@
 }

 public void testBug330313_wksp1_25_njl() {

 	this.formatterPrefs.join_wrapped_lines = false;

-	this.formatterPrefs.wrap_before_binary_operator = false;

 	String source =

 		"package wksp1;\n" + 

 		"\n" + 

@@ -8811,7 +8815,6 @@
 }

 public void testBug330313_wksp1_26_njl() {

 	this.formatterPrefs.join_wrapped_lines = false;

-	this.formatterPrefs.wrap_before_binary_operator = false;

 	String source =

 		"package wksp1;\n" + 

 		"\n" + 

@@ -8962,7 +8965,6 @@
 }

 public void testBug330313_wksp1_30_njl() {

 	this.formatterPrefs.join_wrapped_lines = false;

-	this.formatterPrefs.wrap_before_binary_operator = false;

 	setPageWidth80();

 	String source =

 		"package wksp1;\n" + 

@@ -9083,7 +9085,6 @@
 }

 public void testBug330313_wksp1_33_njl() {

 	this.formatterPrefs.join_wrapped_lines = false;

-	this.formatterPrefs.wrap_before_binary_operator = false;

 	String source =

 		"package wksp1;\n" + 

 		"\n" + 

@@ -9106,8 +9107,8 @@
 		"	void foo() {\n" + 

 		"		if (inMetaTag &&\n" + 

 		"				(t1.image.equalsIgnoreCase(\"name\") ||\n" + 

-		"						t1.image.equalsIgnoreCase(\"HTTP-EQUIV\")) &&\n" + 

-		"				t2 != null) {\n" + 

+		"						t1.image.equalsIgnoreCase(\"HTTP-EQUIV\"))\n" + 

+		"				&& t2 != null) {\n" + 

 		"			currentMetaTag = t2.image.toLowerCase();\n" + 

 		"		}\n" + 

 		"	}\n" + 

@@ -9305,7 +9306,8 @@
 		"	 * 		\"GeneralPage.DoubleClick\", resName, 1,\n" + 

 		"	 * 		new String[][] {\n" + 

 		"	 * 				{ \"Open Browser\", \"open\" },\n" + 

-		"	 * 				{ \"Expand Tree\", \"expand\" } },\n" + 

+		"	 * 				{ \"Expand Tree\", \"expand\" }\n" + 

+		"	 * 		},\n" + 

 		"	 * 		parent);\n" + 

 		"	 * </pre>\n" + 

 		"	 */\n" + 

@@ -9337,7 +9339,8 @@
 		"			/* INACTIVE */ { \"INACTIVE\", \"PARTLY_ACTIVE\", \"PARTLY_ACTIVE\" },\n" + 

 		"			/* PARTLY_ACTIVE */ { \"PARTLY_ACTIVE\", \"PARTLY_ACTIVE\",\n" + 

 		"					\"PARTLY_ACTIVE\" },\n" + 

-		"			/* ACTIVE */ { \"PARTLY_ACTIVE\", \"PARTLY_ACTIVE\", \"ACTIVE\" } };\n" + 

+		"			/* ACTIVE */ { \"PARTLY_ACTIVE\", \"PARTLY_ACTIVE\", \"ACTIVE\" }\n" + 

+		"	};\n" + 

 		"}\n"

 	);

 }

@@ -9508,7 +9511,8 @@
 		"				user,\n" + 

 		"				revision,\n" + 

 		"				String.valueOf(delta),\n" + 

-		"				line });\n" + 

+		"				line\n" + 

+		"		});\n" + 

 		"	}\n" + 

 		"}\n"

 	);

@@ -9611,7 +9615,8 @@
 		"							IWorkbenchThemeConstants.INACTIVE_TAB_TEXT_COLOR),\n" + 

 		"					new Color[] {\n" + 

 		"							colorRegistry.get(\n" + 

-		"									IWorkbenchThemeConstants.INACTIVE_TAB_BG_START) },\n" + 

+		"									IWorkbenchThemeConstants.INACTIVE_TAB_BG_START)\n" + 

+		"					},\n" + 

 		"					new int[0],\n" + 

 		"					true);\n" + 

 		"		}\n" + 

@@ -9780,7 +9785,8 @@
 		"								public char[][] getCompoundName() {\n" + 

 		"									return EvaluationConstants.ROOT_COMPOUND_NAME;\n" + 

 		"								}\n" + 

-		"							} },\n" + 

+		"							}\n" + 

+		"					},\n" + 

 		"					null);\n" + 

 		"		}\n" + 

 		"	}\n" + 

@@ -9985,7 +9991,8 @@
 		"								return info.getLocal()\n" + 

 		"										.getType() == IResource.FILE;\n" + 

 		"							}\n" + 

-		"						} }),\n" + 

+		"						}\n" + 

+		"				}),\n" + 

 		"				// Conflicting changes of files will fail if the local is not\n" + 

 		"				// managed\n" + 

 		"				// or is an addition\n" + 

@@ -10012,7 +10019,8 @@
 		"								}\n" + 

 		"								return false;\n" + 

 		"							}\n" + 

-		"						} }),\n" + 

+		"						}\n" + 

+		"				}),\n" + 

 		"				// Conflicting changes involving a deletion on one side will\n" + 

 		"				// aways fail\n" + 

 		"				new AndSyncInfoFilter(new FastSyncInfoFilter[] {\n" + 

@@ -10031,7 +10039,8 @@
 		"											&& !base.equals(remote));\n" + 

 		"								}\n" + 

 		"							}\n" + 

-		"						} }),\n" + 

+		"						}\n" + 

+		"				}),\n" + 

 		"				// Conflicts where the file type is binary will work but are not\n" + 

 		"				// merged\n" + 

 		"				// so they should be skipped\n" + 

@@ -10060,9 +10069,11 @@
 		"								}\n" + 

 		"								return false;\n" + 

 		"							}\n" + 

-		"						} }),\n" + 

+		"						}\n" + 

+		"				}),\n" + 

 		"				// Outgoing changes may not fail but they are skipped as well\n" + 

-		"				new SyncInfoDirectionFilter(SyncInfo.OUTGOING) });\n" + 

+		"				new SyncInfoDirectionFilter(SyncInfo.OUTGOING)\n" + 

+		"		});\n" + 

 		"	}\n" + 

 		"}\n"

 	);

@@ -10113,7 +10124,8 @@
 		"					{ 104, 20 },\n" + 

 		"					{ 108, 21 },\n" + 

 		"					{ 12, 1856 },\n" + 

-		"					{ 13, 1920 } }, };\n" + 

+		"					{ 13, 1920 } },\n" + 

+		"	};\n" + 

 		"}\n"

 	);

 }

@@ -10254,7 +10266,8 @@
 		"					UNKNOWN,\n" + 

 		"					UNKNOWN,\n" + 

 		"					UNKNOWN,\n" + 

-		"					UNKNOWN } };\n" + 

+		"					UNKNOWN }\n" + 

+		"	};\n" + 

 		"\n" + 

 		"}\n"

 	);

@@ -10300,7 +10313,8 @@
 		"					\"READ_POTENTIAL\",\n" + 

 		"					\"UNKNOWN\",\n" + 

 		"					\"UNKNOWN\",\n" + 

-		"					\"UNKNOWN\" }, };\n" + 

+		"					\"UNKNOWN\" },\n" + 

+		"	};\n" + 

 		"\n" + 

 		"}\n"

 	);

@@ -10348,7 +10362,8 @@
 		"					\"READ_POTENTIAL\",\n" + 

 		"					\"UNKNOWN\",\n" + 

 		"					\"UNKNOWN\",\n" + 

-		"					\"UNKNOWN\" }, };\n" + 

+		"					\"UNKNOWN\" },\n" + 

+		"	};\n" + 

 		"\n" + 

 		"}\n"

 	);

@@ -10389,7 +10404,8 @@
 		"                    \"1234567890123456789012345678901234567890\" },\n" + 

 		"            /* Comment 3 */ {\n" + 

 		"                    \"ABCDEFGHIJKLMNOPQRSTUVWXYZ______________\",\n" + 

-		"                    \"ABCDEFGHIJKLMNOPQRSTUVWXYZ______________\" }, };\n" + 

+		"                    \"ABCDEFGHIJKLMNOPQRSTUVWXYZ______________\" },\n" + 

+		"    };\n" + 

 		"\n" + 

 		"}\n"

 	);

@@ -10720,5 +10736,157 @@
 	String source = "/**/int f;";

 	formatSource(source, source, CodeFormatter.K_STATEMENTS);

 }

-

+/**

+ * @bug 458208: [formatter] follow up bug for comments 

+ * @test test a space is not added after a lambda expression in parenthesis

+ * @see "https://bugs.eclipse.org/bugs/show_bug.cgi?id=458208#c2"

+ */

+public void testBug458208() throws Exception {

+	String source =

+		"package p;\n" + 

+		"import java.util.function.IntConsumer;\n" + 

+		"class TestInlineLambda1 {\n" + 

+		"	{\n" + 

+		"		IntConsumer op = (x -> {}    );\n" + 

+		"	}\n" + 

+		"}\n";

+	formatSource(source,

+		"package p;\n" + 

+		"\n" + 

+		"import java.util.function.IntConsumer;\n" + 

+		"\n" + 

+		"class TestInlineLambda1 {\n" + 

+		"	{\n" + 

+		"		IntConsumer op = (x -> {\n" + 

+		"		});\n" + 

+		"	}\n" + 

+		"}\n"

+	);

+}

+/**

+ * @bug 458208: [formatter] follow up bug for comments 

+ * @test test that comments in switch statements are properly indented

+ * @see "https://bugs.eclipse.org/bugs/show_bug.cgi?id=458208#c21"

+ */

+public void testBug458208b() throws Exception {

+	formatSource(

+		"package p;\n" + 

+		"\n" + 

+		"public class C1 {\n" + 

+		"	void foo(int x) {\n" + 

+		"		switch (x) {\n" + 

+		"		// case 1\n" + 

+		"		case 1:\n" + 

+		"			break;\n" + 

+		"		// case 2\n" + 

+		"		case 2:\n" + 

+		"			break;\n" + 

+		"		// no more cases\n" + 

+		"		}\n" + 

+		"	}\n" + 

+		"\n" + 

+		"	int bar(int x) {\n" + 

+		"		while (true) {\n" + 

+		"			int y = 9;\n" + 

+		"			switch (x) {\n" + 

+		"			// case 1\n" + 

+		"			case 1:\n" + 

+		"				// should return\n" + 

+		"				return y;\n" + 

+		"			// case 2\n" + 

+		"			case 2:\n" + 

+		"				// should break\n" + 

+		"				break;\n" + 

+		"			case 3:\n" + 

+		"				// TODO\n" + 

+		"			}\n" + 

+		"		}\n" + 

+		"	}\n" + 

+		"}\n"

+	);

+}

+/**

+ * @bug 458208: [formatter] follow up bug for comments 

+ * @test test that elements separated with empty lines are properly indented

+ * @see "https://bugs.eclipse.org/bugs/show_bug.cgi?id=458208#c18"

+ */

+public void testBug458208c() throws Exception {

+	final int wrapAllOnColumn = Alignment.M_NEXT_PER_LINE_SPLIT + Alignment.M_INDENT_ON_COLUMN + Alignment.M_FORCE;

+	this.formatterPrefs.alignment_for_enum_constants = wrapAllOnColumn;

+	this.formatterPrefs.alignment_for_arguments_in_enum_constant = wrapAllOnColumn;

+	this.formatterPrefs.alignment_for_expressions_in_array_initializer = wrapAllOnColumn;

+	String source = 

+		"package p;\n" + 

+		"\n" + 

+		"public enum TestEnum {\n" + 

+		"	FIRST_ENUM(\"first type\",\n" + 

+		"	           new SomeClass(),\n" + 

+		"	           new OtherEnumType[] { OtherEnumType.FOO }),\n" + 

+		"\n" + 

+		"	SECOND_ENUM(\"second type\",\n" + 

+		"	            new SomeClassOtherClass(),\n" + 

+		"	            new OtherEnumType[] { OtherEnumType.BAR }),\n" + 

+		"\n" + 

+		"	THIRD_ENUM(\"third type\",\n" + 

+		"	            new YetAnotherClass(),\n" + 

+		"	            new OtherEnumType[] { OtherEnumType.FOOBAR,\n" + 

+		"	                                  OtherEnumType.FOOBARBAZ,\n" + 

+		"\n" + 

+		"	                                  OtherEnumType.LONGERFOOBARBAZ,\n" + 

+		"	                                  OtherEnumType.MORELETTERSINHERE });\n" + 

+		"\n" + 

+		"	/* data members and methods go here */\n" + 

+		"	TestEnum(String s, Cls s1, OtherEnumType[] e) {\n" + 

+		"	}\n" + 

+		"}";

+	formatSource(source,

+		"package p;\n" + 

+		"\n" + 

+		"public enum TestEnum {\n" + 

+		"						FIRST_ENUM(	\"first type\",\n" + 

+		"									new SomeClass(),\n" + 

+		"									new OtherEnumType[] { OtherEnumType.FOO }),\n" + 

+		"\n" + 

+		"						SECOND_ENUM(\"second type\",\n" + 

+		"									new SomeClassOtherClass(),\n" + 

+		"									new OtherEnumType[] { OtherEnumType.BAR }),\n" + 

+		"\n" + 

+		"						THIRD_ENUM(	\"third type\",\n" + 

+		"									new YetAnotherClass(),\n" + 

+		"									new OtherEnumType[] {	OtherEnumType.FOOBAR,\n" + 

+		"															OtherEnumType.FOOBARBAZ,\n" + 

+		"\n" + 

+		"															OtherEnumType.LONGERFOOBARBAZ,\n" + 

+		"															OtherEnumType.MORELETTERSINHERE });\n" + 

+		"\n" + 

+		"	/* data members and methods go here */\n" + 

+		"	TestEnum(String s, Cls s1, OtherEnumType[] e) {\n" + 

+		"	}\n" + 

+		"}"

+	);

+}

+/**

+ * @bug 458208: [formatter] follow up bug for comments 

+ * @test test that enum constants are not indented with spaces when "Use spaces to indent wrapped lines" is on

+ * @see "https://bugs.eclipse.org/bugs/show_bug.cgi?id=458208#c24"

+ */

+public void testBug458208d() throws Exception {

+	this.formatterPrefs.alignment_for_enum_constants = Alignment.M_COMPACT_SPLIT;

+	this.formatterPrefs.use_tabs_only_for_leading_indentations = true;

+	setPageWidth80();

+	String source = 

+		"package p;\n" + 

+		"\n" + 

+		"public enum TestEnum {\n" + 

+		"	ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT, NINE, TEN, ELEVEN, TWELWE, THIRTEEN, FOURTEEN, FIFTEEN;\n" + 

+		"}";

+	formatSource(source,

+		"package p;\n" + 

+		"\n" + 

+		"public enum TestEnum {\n" + 

+		"	ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT, NINE, TEN, ELEVEN, TWELWE,\n" + 

+		"	THIRTEEN, FOURTEEN, FIFTEEN;\n" + 

+		"}"

+	);

+}

 }

diff --git a/org.eclipse.jdt.core/eclipse.jdt.ui.patch.txt b/org.eclipse.jdt.core/eclipse.jdt.ui.patch.txt
deleted file mode 100644
index 676563d..0000000
--- a/org.eclipse.jdt.core/eclipse.jdt.ui.patch.txt
+++ /dev/null
@@ -1,114 +0,0 @@
-### Eclipse Workspace Patch 1.0
-#P org.eclipse.jdt.ui
-diff --git ui/org/eclipse/jdt/internal/ui/preferences/formatter/IndentationTabPage.java ui/org/eclipse/jdt/internal/ui/preferences/formatter/IndentationTabPage.java
-index bbcb3bb..949bf62 100644
---- ui/org/eclipse/jdt/internal/ui/preferences/formatter/IndentationTabPage.java
-+++ ui/org/eclipse/jdt/internal/ui/preferences/formatter/IndentationTabPage.java
-@@ -19,8 +19,6 @@
- import org.eclipse.swt.widgets.Composite;
- import org.eclipse.swt.widgets.Group;
- 
--import org.eclipse.core.runtime.Assert;
--
- import org.eclipse.jdt.core.JavaCore;
- import org.eclipse.jdt.core.formatter.DefaultCodeFormatterConstants;
- 
-@@ -60,7 +58,6 @@
- 	"}";//$NON-NLS-1$
- 
- 	private CompilationUnitPreview fPreview;
--	private String fOldTabChar= null;
- 
- 	public IndentationTabPage(ModifyDialog modifyDialog, Map<String, String> workingValues) {
- 		super(modifyDialog, workingValues);
-@@ -79,21 +76,17 @@
- 		};
- 		final ComboPreference tabPolicy= createComboPref(generalGroup, numColumns, FormatterMessages.IndentationTabPage_general_group_option_tab_policy, DefaultCodeFormatterConstants.FORMATTER_TAB_CHAR, tabPolicyValues, tabPolicyLabels);
- 		final CheckboxPreference onlyForLeading= createCheckboxPref(generalGroup, numColumns, FormatterMessages.IndentationTabPage_use_tabs_only_for_leading_indentations, DefaultCodeFormatterConstants.FORMATTER_USE_TABS_ONLY_FOR_LEADING_INDENTATIONS, FALSE_TRUE);
--		final NumberPreference indentSize= createNumberPref(generalGroup, numColumns, FormatterMessages.IndentationTabPage_general_group_option_indent_size, DefaultCodeFormatterConstants.FORMATTER_TAB_SIZE, 0, 32);
-+		final NumberPreference indentSize= createNumberPref(generalGroup, numColumns, FormatterMessages.IndentationTabPage_general_group_option_indent_size, DefaultCodeFormatterConstants.FORMATTER_INDENTATION_SIZE, 0, 32);
- 		final NumberPreference tabSize= createNumberPref(generalGroup, numColumns, FormatterMessages.IndentationTabPage_general_group_option_tab_size, DefaultCodeFormatterConstants.FORMATTER_TAB_SIZE, 0, 32);
- 
--		String tabchar= fWorkingValues.get(DefaultCodeFormatterConstants.FORMATTER_TAB_CHAR);
--		updateTabPreferences(tabchar, tabSize, indentSize, onlyForLeading);
--		tabPolicy.addObserver(new Observer() {
-+		updateTabPreferences(indentSize, onlyForLeading);
-+		Observer tabObserver = new Observer() {
- 			public void update(Observable o, Object arg) {
--				updateTabPreferences((String) arg, tabSize, indentSize, onlyForLeading);
-+				updateTabPreferences(indentSize, onlyForLeading);
- 			}
--		});
--		tabSize.addObserver(new Observer() {
--			public void update(Observable o, Object arg) {
--				indentSize.updateWidget();
--			}
--		});
-+		};
-+		tabPolicy.addObserver(tabObserver);
-+		tabSize.addObserver(tabObserver);
- 
- 		final Group typeMemberGroup= createGroup(numColumns, composite, FormatterMessages.IndentationTabPage_field_alignment_group_title);
- 		createCheckboxPref(typeMemberGroup, numColumns, FormatterMessages.IndentationTabPage_field_alignment_group_align_fields_in_columns, DefaultCodeFormatterConstants.FORMATTER_ALIGN_TYPE_MEMBERS_ON_COLUMNS, FALSE_TRUE);
-@@ -141,50 +134,17 @@
-         fPreview.update();
-     }
- 
--	private void updateTabPreferences(String tabPolicy, NumberPreference tabPreference, NumberPreference indentPreference, CheckboxPreference onlyForLeading) {
--		/*
--		 * If the tab-char is SPACE (or TAB), INDENTATION_SIZE
--		 * preference is not used by the core formatter. We piggy back the
--		 * visual tab length setting in that preference in that case. If the
--		 * user selects MIXED, we use the previous TAB_SIZE preference as the
--		 * new INDENTATION_SIZE (as this is what it really is) and set the
--		 * visual tab size to the value piggy backed in the INDENTATION_SIZE
--		 * preference. See also CodeFormatterUtil.
--		 */
--		if (DefaultCodeFormatterConstants.MIXED.equals(tabPolicy)) {
--			if (JavaCore.SPACE.equals(fOldTabChar) || JavaCore.TAB.equals(fOldTabChar))
--				swapTabValues();
--			tabPreference.setEnabled(true);
--			tabPreference.setKey(DefaultCodeFormatterConstants.FORMATTER_TAB_SIZE);
--			indentPreference.setEnabled(true);
--			indentPreference.setKey(DefaultCodeFormatterConstants.FORMATTER_INDENTATION_SIZE);
--			onlyForLeading.setEnabled(true);
--		} else if (JavaCore.SPACE.equals(tabPolicy)) {
--			if (DefaultCodeFormatterConstants.MIXED.equals(fOldTabChar))
--				swapTabValues();
--			tabPreference.setEnabled(true);
--			tabPreference.setKey(DefaultCodeFormatterConstants.FORMATTER_INDENTATION_SIZE);
--			indentPreference.setEnabled(true);
--			indentPreference.setKey(DefaultCodeFormatterConstants.FORMATTER_TAB_SIZE);
--			onlyForLeading.setEnabled(false);
--		} else if (JavaCore.TAB.equals(tabPolicy)) {
--			if (DefaultCodeFormatterConstants.MIXED.equals(fOldTabChar))
--				swapTabValues();
--			tabPreference.setEnabled(true);
--			tabPreference.setKey(DefaultCodeFormatterConstants.FORMATTER_TAB_SIZE);
--			indentPreference.setEnabled(false);
--			indentPreference.setKey(DefaultCodeFormatterConstants.FORMATTER_TAB_SIZE);
--			onlyForLeading.setEnabled(true);
--		} else {
--			Assert.isTrue(false);
--		}
--		fOldTabChar= tabPolicy;
--	}
-+	private void updateTabPreferences(NumberPreference indentPreference, CheckboxPreference onlyForLeading) {
-+		String tabPolicy = fWorkingValues.get(DefaultCodeFormatterConstants.FORMATTER_TAB_CHAR);
-+		onlyForLeading.setEnabled(!JavaCore.SPACE.equals(tabPolicy));
- 
--	private void swapTabValues() {
--		String tabSize= fWorkingValues.get(DefaultCodeFormatterConstants.FORMATTER_TAB_SIZE);
--		String indentSize= fWorkingValues.get(DefaultCodeFormatterConstants.FORMATTER_INDENTATION_SIZE);
--		fWorkingValues.put(DefaultCodeFormatterConstants.FORMATTER_TAB_SIZE, indentSize);
--		fWorkingValues.put(DefaultCodeFormatterConstants.FORMATTER_INDENTATION_SIZE, tabSize);
-+		if (JavaCore.TAB.equals(tabPolicy)) {
-+			// indentation size preference must be disabled and show the same value as tab size 
-+			String tabSize= fWorkingValues.get(DefaultCodeFormatterConstants.FORMATTER_TAB_SIZE);
-+			fWorkingValues.put(DefaultCodeFormatterConstants.FORMATTER_INDENTATION_SIZE, tabSize);
-+			indentPreference.setEnabled(false);
-+		} else {
-+			indentPreference.setEnabled(true);
-+		}
- 	}
- }
\ No newline at end of file
diff --git a/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/DefaultCodeFormatter.java b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/DefaultCodeFormatter.java
index 7cceb88..f7a3580 100644
--- a/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/DefaultCodeFormatter.java
+++ b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/DefaultCodeFormatter.java
@@ -11,6 +11,7 @@
  *								bug 404146 - [1.7][compiler] nested try-catch-finally-blocks leads to unrunnable Java byte code
  *     Harry Terkelsen (het@google.com) - Bug 449262 - Allow the use of third-party Java formatters
  *     Mateusz Matela <mateusz.matela@gmail.com> - [formatter] Formatter does not format Java code correctly, especially when max line width is set - https://bugs.eclipse.org/303519
+ *     Mateusz Matela <mateusz.matela@gmail.com> - [formatter] follow up bug for comments - https://bugs.eclipse.org/458208
  *******************************************************************************/
 package org.eclipse.jdt.internal.formatter;
 
@@ -369,7 +370,7 @@
 	private void prepareWraps(int kind) {
 		WrapPreparator wrapPreparator = new WrapPreparator(this.tokenManager, this.workingOptions, kind);
 		this.astRoot.accept(wrapPreparator);
-		wrapPreparator.finishUp();
+		wrapPreparator.finishUp(this.astRoot);
 	}
 
 	/**
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 f7ff003..32640ec 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
@@ -8,6 +8,7 @@
  * Contributors:
  *     Mateusz Matela <mateusz.matela@gmail.com> - [formatter] Formatter does not format Java code correctly, especially when max line width is set - https://bugs.eclipse.org/303519
  *     Mateusz Matela <mateusz.matela@gmail.com> - [formatter] IndexOutOfBoundsException in TokenManager - https://bugs.eclipse.org/462945
+ *     Mateusz Matela <mateusz.matela@gmail.com> - [formatter] follow up bug for comments - https://bugs.eclipse.org/458208
  *******************************************************************************/
 package org.eclipse.jdt.internal.formatter;
 
@@ -54,6 +55,7 @@
 import org.eclipse.jdt.core.dom.Modifier;
 import org.eclipse.jdt.core.dom.NormalAnnotation;
 import org.eclipse.jdt.core.dom.PackageDeclaration;
+import org.eclipse.jdt.core.dom.ReturnStatement;
 import org.eclipse.jdt.core.dom.SingleMemberAnnotation;
 import org.eclipse.jdt.core.dom.SingleVariableDeclaration;
 import org.eclipse.jdt.core.dom.Statement;
@@ -291,35 +293,41 @@
 		handleBracedCode(node, node.getExpression(), this.options.brace_position_for_switch,
 				this.options.indent_switchstatements_compare_to_switch, true);
 
+		List<Statement> statements = node.statements();
 		if (this.options.indent_switchstatements_compare_to_cases) {
-			int openBraceIndex = this.tm.firstIndexIn(node, TokenNameLBRACE);
-			this.tm.get(openBraceIndex + 1).indent();
-			int closeBraceIndex = this.tm.lastIndexIn(node, TokenNameRBRACE);
-			this.tm.get(closeBraceIndex).unindent();
+			int nonBreakStatementEnd = -1;
+			for (Statement statement : statements) {
+				if (statement instanceof SwitchCase) {
+					if (nonBreakStatementEnd >= 0) {
+						// indent only comments between previous and current statement
+						this.tm.get(nonBreakStatementEnd + 1).indent();
+						this.tm.firstTokenIn(statement, -1).unindent();
+					}
+				} else if (!(statement instanceof BreakStatement || statement instanceof Block)) {
+					indent(statement);
+				}
+				nonBreakStatementEnd = (statement instanceof BreakStatement || statement instanceof ReturnStatement)
+						? -1 : this.tm.lastIndexIn(statement, -1);
+			}
+			if (nonBreakStatementEnd >= 0) {
+				// indent comments between last statement and closing brace 
+				this.tm.get(nonBreakStatementEnd + 1).indent();
+				this.tm.lastTokenIn(node, TokenNameRBRACE).unindent();
+			}
+		}
+		if (this.options.indent_breaks_compare_to_cases) {
+			for (Statement statement : statements) {
+				if (statement instanceof BreakStatement)
+					indent(statement);
+			}
 		}
 
-		boolean isBreakStatement = false;
-		List<Statement> statements = node.statements();
 		for (Statement statement : statements) {
-			if (isBreakStatement) // actually, was break statement
-				this.tm.firstTokenIn(statement, -1).indent();
-			isBreakStatement = statement instanceof BreakStatement;
-			if (this.options.indent_switchstatements_compare_to_cases
-					&& (isBreakStatement || statement instanceof SwitchCase || statement instanceof Block)) {
-				unindent(statement);
-			}
 			if (statement instanceof Block)
 				continue; // will add break in visit(Block) if necessary
 			if (this.options.put_empty_statement_on_new_line || !(statement instanceof EmptyStatement))
 				breakLineBefore(statement);
-			if (isBreakStatement) {
-				if (this.options.indent_breaks_compare_to_cases)
-					indent(statement);
-				this.tm.firstTokenAfter(statement, -1).unindent();
-			}
 		}
-		if (isBreakStatement) // actually, was break statement
-			this.tm.lastTokenIn(node, -1).indent();
 
 		return true;
 	}
@@ -569,8 +577,7 @@
 
 	private void indent(ASTNode node) {
 		int startIndex = this.tm.firstIndexIn(node, -1);
-		while (startIndex > 0 && this.tm.get(startIndex - 1).isComment()
-				&& !(node.getParent() instanceof SwitchStatement))
+		while (startIndex > 0 && this.tm.get(startIndex - 1).isComment())
 			startIndex--;
 		this.tm.get(startIndex).indent();
 		int lastIndex = this.tm.lastIndexIn(node, -1);
@@ -578,16 +585,6 @@
 			this.tm.get(lastIndex + 1).unindent();
 	}
 
-	private void unindent(ASTNode node) {
-		int startIndex = this.tm.firstIndexIn(node, -1);
-		// no symmetry with indent(): unindent is only used in switch statement
-		// and should not include preceding comments
-		this.tm.get(startIndex).unindent();
-		int lastIndex = this.tm.lastIndexIn(node, -1);
-		if (lastIndex + 1 < this.tm.size())
-			this.tm.get(lastIndex + 1).indent();
-	}
-
 	public void finishUp() {
 		// the visits only noted where indents increase and decrease,
 		// now prepare actual indent values
diff --git a/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/SpacePreparator.java b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/SpacePreparator.java
index da420e1..63a49a4 100644
--- a/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/SpacePreparator.java
+++ b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/SpacePreparator.java
@@ -8,6 +8,7 @@
  * Contributors:

  *     Mateusz Matela <mateusz.matela@gmail.com> - [formatter] Formatter does not format Java code correctly, especially when max line width is set - https://bugs.eclipse.org/303519

  *     Mateusz Matela <mateusz.matela@gmail.com> - [formatter] IndexOutOfBoundsException in TokenManager - https://bugs.eclipse.org/462945

+ *     Mateusz Matela <mateusz.matela@gmail.com> - [formatter] follow up bug for comments - https://bugs.eclipse.org/458208

  *******************************************************************************/

 package org.eclipse.jdt.internal.formatter;

 

@@ -497,9 +498,11 @@
 		handleToken(node, TokenNameLBRACE, this.options.insert_space_before_opening_brace_in_block, false);

 		if (this.options.insert_space_after_closing_brace_in_block) {

 			int closeBraceIndex = this.tm.lastIndexIn(node, TokenNameRBRACE);

-			if (closeBraceIndex + 1 < this.tm.size()

-					&& this.tm.get(closeBraceIndex + 1).tokenType != TokenNameSEMICOLON)

-				this.tm.get(closeBraceIndex).spaceAfter();

+			if (closeBraceIndex + 1 < this.tm.size()) {

+				int nextToken = this.tm.get(closeBraceIndex + 1).tokenType;

+				if (nextToken != TokenNameSEMICOLON && nextToken != TokenNameRPAREN)

+					this.tm.get(closeBraceIndex).spaceAfter();

+			}

 		}

 		return true;

 	}

diff --git a/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/linewrap/WrapExecutor.java b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/linewrap/WrapExecutor.java
index af9486b..c06dc48 100644
--- a/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/linewrap/WrapExecutor.java
+++ b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/linewrap/WrapExecutor.java
@@ -7,6 +7,7 @@
  *
  * Contributors:
  *     Mateusz Matela <mateusz.matela@gmail.com> - [formatter] Formatter does not format Java code correctly, especially when max line width is set - https://bugs.eclipse.org/303519
+ *     Mateusz Matela <mateusz.matela@gmail.com> - [formatter] follow up bug for comments - https://bugs.eclipse.org/458208
  *******************************************************************************/
 package org.eclipse.jdt.internal.formatter.linewrap;
 
@@ -631,7 +632,7 @@
 
 	int getWrapIndent(Token token) {
 		WrapPolicy policy = token.getWrapPolicy();
-		if (policy == null || (token.getLineBreaksBefore() > 1 && !policy.isForced))
+		if (policy == null || (token.getLineBreaksBefore() > 1 && !policy.isForced && !policy.isTopPriority()))
 			return token.getIndent(); // no additional indentation after an empty line
 
 		if (this.options.never_indent_line_comments_on_first_column && token.tokenType == TokenNameCOMMENT_LINE
diff --git a/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/linewrap/WrapPreparator.java b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/linewrap/WrapPreparator.java
index a49ce78..b973b6f 100644
--- a/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/linewrap/WrapPreparator.java
+++ b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/linewrap/WrapPreparator.java
@@ -7,6 +7,7 @@
  *
  * Contributors:
  *     Mateusz Matela <mateusz.matela@gmail.com> - [formatter] Formatter does not format Java code correctly, especially when max line width is set - https://bugs.eclipse.org/303519
+ *     Mateusz Matela <mateusz.matela@gmail.com> - [formatter] follow up bug for comments - https://bugs.eclipse.org/458208
  *******************************************************************************/
 package org.eclipse.jdt.internal.formatter.linewrap;
 
@@ -20,10 +21,12 @@
 import static org.eclipse.jdt.internal.compiler.parser.TerminalTokens.TokenNameLPAREN;
 import static org.eclipse.jdt.internal.compiler.parser.TerminalTokens.TokenNameOR;
 import static org.eclipse.jdt.internal.compiler.parser.TerminalTokens.TokenNameQUESTION;
+import static org.eclipse.jdt.internal.compiler.parser.TerminalTokens.TokenNameRBRACE;
 import static org.eclipse.jdt.internal.compiler.parser.TerminalTokens.TokenNameRPAREN;
 import static org.eclipse.jdt.internal.compiler.parser.TerminalTokens.TokenNameStringLiteral;
 import static org.eclipse.jdt.internal.compiler.parser.TerminalTokens.TokenNameextends;
 import static org.eclipse.jdt.internal.compiler.parser.TerminalTokens.TokenNameimplements;
+import static org.eclipse.jdt.internal.compiler.parser.TerminalTokens.TokenNameIdentifier;
 import static org.eclipse.jdt.internal.compiler.parser.TerminalTokens.TokenNamenew;
 import static org.eclipse.jdt.internal.compiler.parser.TerminalTokens.TokenNamethrows;
 
@@ -358,14 +361,22 @@
 			if (operand instanceof InfixExpression && samePrecedence(node, (InfixExpression) operand)) {
 				findTokensToWrap((InfixExpression) operand, depth + 1);
 			}
-			if (this.options.wrap_before_binary_operator) {
-				int index = this.tm.firstIndexBefore(operand, -1);
-				while (this.tm.get(index).isComment())
-					index--;
-				assert node.getOperator().toString().equals(this.tm.toString(index));
-				this.wrapIndexes.add(index);
-			} else {
-				this.wrapIndexes.add(this.tm.firstIndexIn(operand, -1));
+			int indexBefore = this.tm.firstIndexBefore(operand, -1);
+			while (this.tm.get(indexBefore).isComment())
+				indexBefore--;
+			assert node.getOperator().toString().equals(this.tm.toString(indexBefore));
+			int indexAfter = this.tm.firstIndexIn(operand, -1);
+			this.wrapIndexes.add(this.options.wrap_before_binary_operator ? indexBefore : indexAfter);
+
+			if (!this.options.join_wrapped_lines) {
+				// TODO there should be an option for never joining wraps on opposite side of the operator
+				if (this.options.wrap_before_binary_operator) {
+					if (this.tm.countLineBreaksBetween(this.tm.get(indexAfter - 1), this.tm.get(indexAfter)) > 0)
+						this.wrapIndexes.add(indexAfter);
+				} else {
+					if (this.tm.countLineBreaksBetween(this.tm.get(indexBefore), this.tm.get(indexBefore - 1)) > 0)
+						this.wrapIndexes.add(indexBefore);
+				}
 			}
 		}
 	}
@@ -398,6 +409,17 @@
 			this.wrapGroupEnd = this.tm.lastIndexIn(node, -1);
 			handleWrap(this.options.alignment_for_expressions_in_array_initializer, node);
 		}
+		if (!this.options.join_wrapped_lines
+				&& !this.options.insert_new_line_before_closing_brace_in_array_initializer) {
+			// if there is a line break before the closing brace, formatter should treat it as a valid wrap to preserve
+			int closingBraceIndex = this.tm.lastIndexIn(node, TokenNameRBRACE);
+			Token closingBrace = this.tm.get(closingBraceIndex);
+			if (this.tm.countLineBreaksBetween(this.tm.get(closingBraceIndex - 1), closingBrace) == 1) {
+				int openingBraceIndex = this.tm.firstIndexIn(node, TokenNameLBRACE);
+				closingBrace.setWrapPolicy(
+						new WrapPolicy(0, openingBraceIndex, this.currentDepth, 1, true, false, -1, false));
+			}
+		}
 		return true;
 	}
 
@@ -679,12 +701,13 @@
 				indentOnColumn, topPriorityGroupEnd, false);
 	}
 
-	public void finishUp() {
+	public void finishUp(ASTNode astRoot) {
 		preserveExistingLineBreaks();
 		new WrapExecutor(this.tm, this.options).executeWraps();
 		if (this.fieldAligner != null)
 			this.fieldAligner.alignComments();
 		wrapComments();
+		fixEnumConstantIndents(astRoot);
 	}
 
 	private void preserveExistingLineBreaks() {
@@ -769,4 +792,18 @@
 			}
 		}
 	}
+
+	private void fixEnumConstantIndents(ASTNode astRoot) {
+		if (this.options.use_tabs_only_for_leading_indentations) {
+			// enum constants should be indented like other declarations, not like wrapped elements
+			astRoot.accept(new ASTVisitor() {
+
+				@Override
+				public boolean visit(EnumConstantDeclaration node) {
+					WrapPreparator.this.tm.firstTokenIn(node, TokenNameIdentifier).setWrapPolicy(null);
+					return true;
+				}
+			});
+		}
+	}
 }