diff options
author | Mateusz Matela | 2019-10-08 20:40:25 +0000 |
---|---|---|
committer | Mateusz Matela | 2019-10-08 20:45:31 +0000 |
commit | 2540a567a49e5736ed7769d5bc50c85b8314171c (patch) | |
tree | 14d508b79b82fc1bb2df05d96b8fa7c6f4e13d8b | |
parent | 51e712414a50db93088614af3f0b6d18e631a418 (diff) | |
download | eclipse.jdt.core-2540a567a49e5736ed7769d5bc50c85b8314171c.tar.gz eclipse.jdt.core-2540a567a49e5736ed7769d5bc50c85b8314171c.tar.xz eclipse.jdt.core-2540a567a49e5736ed7769d5bc50c85b8314171c.zip |
Change-Id: I761723da09f2747fee817dfb030cc12938ba22b1
Signed-off-by: Mateusz Matela <mateusz.matela@gmail.com>
21 files changed, 1376 insertions, 36 deletions
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 320fe9a757..567280f757 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 @@ -15242,4 +15242,147 @@ public void testBug390720b() throws JavaModelException { this.formatterPrefs.blank_lines_between_statement_groups_in_switch = ~0; formatSourceInWorkspace("test390720", "in.java", "B_out.java"); } +/** + * https://bugs.eclipse.org/549436 - [13] Formatter support for JEP 355 Text Block + */ +public void testBug549436a() throws JavaModelException { + setComplianceLevel(CompilerOptions.VERSION_13); + setPageWidth80(); + this.formatterPrefs.tab_char = DefaultCodeFormatterOptions.SPACE; + this.formatterPrefs.use_tabs_only_for_leading_indentations = false; + this.formatterPrefs.indent_empty_lines = false; + this.formatterPrefs.text_block_indentation = Alignment.M_INDENT_PRESERVE; + this.formatterPrefs.continuation_indentation = 2; + formatSourceInWorkspace("test549436", "in.java", "A_out.java"); +} +/** + * https://bugs.eclipse.org/549436 - [13] Formatter support for JEP 355 Text Block + */ +public void testBug549436b() throws JavaModelException { + setComplianceLevel(CompilerOptions.VERSION_13); + setPageWidth80(); + this.formatterPrefs.tab_char = DefaultCodeFormatterOptions.SPACE; + this.formatterPrefs.use_tabs_only_for_leading_indentations = false; + this.formatterPrefs.indent_empty_lines = false; + this.formatterPrefs.text_block_indentation = Alignment.M_INDENT_BY_ONE; + this.formatterPrefs.continuation_indentation = 2; + formatSourceInWorkspace("test549436", "in.java", "B_out.java"); +} +/** + * https://bugs.eclipse.org/549436 - [13] Formatter support for JEP 355 Text Block + */ +public void testBug549436c() throws JavaModelException { + setComplianceLevel(CompilerOptions.VERSION_13); + setPageWidth80(); + this.formatterPrefs.tab_char = DefaultCodeFormatterOptions.SPACE; + this.formatterPrefs.use_tabs_only_for_leading_indentations = false; + this.formatterPrefs.indent_empty_lines = false; + this.formatterPrefs.text_block_indentation = Alignment.M_INDENT_DEFAULT; + this.formatterPrefs.continuation_indentation = 2; + formatSourceInWorkspace("test549436", "in.java", "C_out.java"); +} +/** + * https://bugs.eclipse.org/549436 - [13] Formatter support for JEP 355 Text Block + */ +public void testBug549436d() throws JavaModelException { + setComplianceLevel(CompilerOptions.VERSION_13); + setPageWidth80(); + this.formatterPrefs.tab_char = DefaultCodeFormatterOptions.SPACE; + this.formatterPrefs.use_tabs_only_for_leading_indentations = false; + this.formatterPrefs.indent_empty_lines = false; + this.formatterPrefs.text_block_indentation = Alignment.M_INDENT_DEFAULT; + this.formatterPrefs.continuation_indentation = 3; + formatSourceInWorkspace("test549436", "in.java", "D_out.java"); +} +/** + * https://bugs.eclipse.org/549436 - [13] Formatter support for JEP 355 Text Block + */ +public void testBug549436e() throws JavaModelException { + setComplianceLevel(CompilerOptions.VERSION_13); + setPageWidth80(); + this.formatterPrefs.tab_char = DefaultCodeFormatterOptions.SPACE; + this.formatterPrefs.use_tabs_only_for_leading_indentations = false; + this.formatterPrefs.indent_empty_lines = false; + this.formatterPrefs.text_block_indentation = Alignment.M_INDENT_ON_COLUMN; + this.formatterPrefs.continuation_indentation = 2; + formatSourceInWorkspace("test549436", "in.java", "E_out.java"); +} +/** + * https://bugs.eclipse.org/549436 - [13] Formatter support for JEP 355 Text Block + */ +public void testBug549436f() throws JavaModelException { + setComplianceLevel(CompilerOptions.VERSION_13); + setPageWidth80(); + this.formatterPrefs.tab_char = DefaultCodeFormatterOptions.TAB; + this.formatterPrefs.use_tabs_only_for_leading_indentations = false; + this.formatterPrefs.indent_empty_lines = false; + this.formatterPrefs.text_block_indentation = Alignment.M_INDENT_BY_ONE; + this.formatterPrefs.continuation_indentation = 2; + formatSourceInWorkspace("test549436", "in.java", "F_out.java"); +} +/** + * https://bugs.eclipse.org/549436 - [13] Formatter support for JEP 355 Text Block + */ +public void testBug549436g() throws JavaModelException { + setComplianceLevel(CompilerOptions.VERSION_13); + setPageWidth80(); + this.formatterPrefs.tab_char = DefaultCodeFormatterOptions.TAB; + this.formatterPrefs.use_tabs_only_for_leading_indentations = false; + this.formatterPrefs.indent_empty_lines = true; + this.formatterPrefs.text_block_indentation = Alignment.M_INDENT_DEFAULT; + this.formatterPrefs.continuation_indentation = 2; + formatSourceInWorkspace("test549436", "in.java", "G_out.java"); +} +/** + * https://bugs.eclipse.org/549436 - [13] Formatter support for JEP 355 Text Block + */ +public void testBug549436h() throws JavaModelException { + setComplianceLevel(CompilerOptions.VERSION_13); + setPageWidth80(); + this.formatterPrefs.tab_char = DefaultCodeFormatterOptions.TAB; + this.formatterPrefs.use_tabs_only_for_leading_indentations = true; + this.formatterPrefs.indent_empty_lines = false; + this.formatterPrefs.text_block_indentation = Alignment.M_INDENT_DEFAULT; + this.formatterPrefs.continuation_indentation = 3; + formatSourceInWorkspace("test549436", "in.java", "H_out.java"); +} +/** + * https://bugs.eclipse.org/549436 - [13] Formatter support for JEP 355 Text Block + */ +public void testBug549436i() throws JavaModelException { + setComplianceLevel(CompilerOptions.VERSION_13); + setPageWidth80(); + this.formatterPrefs.tab_char = DefaultCodeFormatterOptions.TAB; + this.formatterPrefs.use_tabs_only_for_leading_indentations = true; + this.formatterPrefs.indent_empty_lines = true; + this.formatterPrefs.text_block_indentation = Alignment.M_INDENT_ON_COLUMN; + this.formatterPrefs.continuation_indentation = 2; + formatSourceInWorkspace("test549436", "in.java", "I_out.java"); +} +/** + * https://bugs.eclipse.org/549436 - [13] Formatter support for JEP 355 Text Block + */ +public void testBug549436j() throws JavaModelException { + setComplianceLevel(CompilerOptions.VERSION_13); + setPageWidth80(); + this.formatterPrefs.tab_char = DefaultCodeFormatterOptions.MIXED; + this.formatterPrefs.use_tabs_only_for_leading_indentations = false; + this.formatterPrefs.indent_empty_lines = false; + this.formatterPrefs.text_block_indentation = Alignment.M_INDENT_ON_COLUMN; + this.formatterPrefs.continuation_indentation = 2; + formatSourceInWorkspace("test549436", "in.java", "J_out.java"); +} +/** + * https://bugs.eclipse.org/549436 - [13] Formatter support for JEP 355 Text Block + */ +public void testBug549436k() throws JavaModelException { + setComplianceLevel(CompilerOptions.VERSION_13); + setPageWidth80(); + this.formatterPrefs.tab_char = DefaultCodeFormatterOptions.TAB; + this.formatterPrefs.use_tabs_only_for_leading_indentations = false; + this.formatterPrefs.indent_empty_lines = false; + this.formatterPrefs.text_block_indentation = Alignment.M_INDENT_ON_COLUMN; + this.formatterPrefs.continuation_indentation = 2; + formatSourceInWorkspace("test549436", "in.java", "K_out.java"); +} } diff --git a/org.eclipse.jdt.core.tests.model/workspace/Formatter/test549436/A_out.java b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test549436/A_out.java new file mode 100644 index 0000000000..d9109d5484 --- /dev/null +++ b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test549436/A_out.java @@ -0,0 +1,86 @@ +public class Example { + String s = """ +aaa + +bbb + + +ccc +"""; + + String s2 = """ + aaa + + bbb + + + ccc""" + Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, + 9, 0, 1, 2, 3, 4, 5); + + Object[] s3 = { "aaaa", """ + bbb + + ccc + + + ddd + """, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, + 2, 3, 4, 5 }; + + Object[] s4 = { "aaaa", // + """ + bbb + + ccc + + + ddd + """, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, + 5 }; + + void foo() { + Arrays.asList(""" + """, """ + 1""", """ + 2 + """, // + "", """ + + + + """, /**/ + """ +aaa + """); + + Object o = new Object(""" + a,b,c,d""".split(""" + ,""")) { + { + System.out.println(""" + aaaaaaaaaaaaaaa + + bbbbbbbbbbbbbb"""); + } + + String bar(boolean arg) { + return (arg ? """ + aaaa + """ : """ + bbb + """) + (arg + ? "cccccccccc" + "ddddddddddd" + "eeeeeeeeee" + + "fffffffffff" + "ggggggggg" + """ + hhhhhhhh""" + : """ + aaaaaaaaa""" + """ + bbbbbbbbb""" + """ + cccccccccccc""" + """ + ddddddddddddd + """ + "eeeeeeee" + "fffffffffffff" + "ggggggggggggggggg" + + "hhhhhhhhhhhhhhh" + "iiiiiiiiiiiiiiii" + + "jjjjjjjjjjjjjjjjjjjjjjj"); + } + }; + } +} diff --git a/org.eclipse.jdt.core.tests.model/workspace/Formatter/test549436/B_out.java b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test549436/B_out.java new file mode 100644 index 0000000000..6a5cd62eff --- /dev/null +++ b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test549436/B_out.java @@ -0,0 +1,87 @@ +public class Example { + String s = """ + aaa + + bbb + + + ccc + """; + + String s2 = """ + aaa + + bbb + + + ccc""" + Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, + 7, 8, 9, 0, 1, 2, 3, 4, 5); + + Object[] s3 = { "aaaa", """ + bbb + + ccc + + + ddd + """, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, + 3, 4, 5 }; + + Object[] s4 = { "aaaa", // + """ + bbb + + ccc + + + ddd + """, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, + 1, 2, 3, 4, 5 }; + + void foo() { + Arrays.asList(""" + """, """ + 1""", """ + 2 + """, // + "", """ + + + + """, /**/ + """ + aaa + """); + + Object o = new Object(""" + a,b,c,d""".split(""" + ,""")) { + { + System.out.println(""" + aaaaaaaaaaaaaaa + + bbbbbbbbbbbbbb"""); + } + + String bar(boolean arg) { + return (arg ? """ + aaaa + """ : """ + bbb + """) + (arg + ? "cccccccccc" + "ddddddddddd" + "eeeeeeeeee" + + "fffffffffff" + "ggggggggg" + """ + hhhhhhhh""" + : """ + aaaaaaaaa""" + """ + bbbbbbbbb""" + """ + cccccccccccc""" + """ + ddddddddddddd + """ + "eeeeeeee" + "fffffffffffff" + + "ggggggggggggggggg" + "hhhhhhhhhhhhhhh" + + "iiiiiiiiiiiiiiii" + + "jjjjjjjjjjjjjjjjjjjjjjj"); + } + }; + } +} diff --git a/org.eclipse.jdt.core.tests.model/workspace/Formatter/test549436/C_out.java b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test549436/C_out.java new file mode 100644 index 0000000000..220456b74d --- /dev/null +++ b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test549436/C_out.java @@ -0,0 +1,87 @@ +public class Example { + String s = """ + aaa + + bbb + + + ccc + """; + + String s2 = """ + aaa + + bbb + + + ccc""" + Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, + 6, 7, 8, 9, 0, 1, 2, 3, 4, 5); + + Object[] s3 = { "aaaa", """ + bbb + + ccc + + + ddd + """, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, + 2, 3, 4, 5 }; + + Object[] s4 = { "aaaa", // + """ + bbb + + ccc + + + ddd + """, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, + 9, 0, 1, 2, 3, 4, 5 }; + + void foo() { + Arrays.asList(""" + """, """ + 1""", """ + 2 + """, // + "", """ + + + + """, /**/ + """ + aaa + """); + + Object o = new Object(""" + a,b,c,d""".split(""" + ,""")) { + { + System.out.println(""" + aaaaaaaaaaaaaaa + + bbbbbbbbbbbbbb"""); + } + + String bar(boolean arg) { + return (arg ? """ + aaaa + """ : """ + bbb + """) + (arg + ? "cccccccccc" + "ddddddddddd" + "eeeeeeeeee" + + "fffffffffff" + "ggggggggg" + """ + hhhhhhhh""" + : """ + aaaaaaaaa""" + """ + bbbbbbbbb""" + """ + cccccccccccc""" + """ + ddddddddddddd + """ + "eeeeeeee" + "fffffffffffff" + + "ggggggggggggggggg" + "hhhhhhhhhhhhhhh" + + "iiiiiiiiiiiiiiii" + + "jjjjjjjjjjjjjjjjjjjjjjj"); + } + }; + } +} diff --git a/org.eclipse.jdt.core.tests.model/workspace/Formatter/test549436/D_out.java b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test549436/D_out.java new file mode 100644 index 0000000000..909d32645c --- /dev/null +++ b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test549436/D_out.java @@ -0,0 +1,87 @@ +public class Example { + String s = """ + aaa + + bbb + + + ccc + """; + + String s2 = """ + aaa + + bbb + + + ccc""" + Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, + 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5); + + Object[] s3 = { "aaaa", """ + bbb + + ccc + + + ddd + """, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, + 1, 2, 3, 4, 5 }; + + Object[] s4 = { "aaaa", // + """ + bbb + + ccc + + + ddd + """, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, + 8, 9, 0, 1, 2, 3, 4, 5 }; + + void foo() { + Arrays.asList(""" + """, """ + 1""", """ + 2 + """, // + "", """ + + + + """, /**/ + """ + aaa + """); + + Object o = new Object(""" + a,b,c,d""".split(""" + ,""")) { + { + System.out.println(""" + aaaaaaaaaaaaaaa + + bbbbbbbbbbbbbb"""); + } + + String bar(boolean arg) { + return (arg ? """ + aaaa + """ : """ + bbb + """) + (arg + ? "cccccccccc" + "ddddddddddd" + "eeeeeeeeee" + + "fffffffffff" + "ggggggggg" + """ + hhhhhhhh""" + : """ + aaaaaaaaa""" + """ + bbbbbbbbb""" + """ + cccccccccccc""" + """ + ddddddddddddd + """ + "eeeeeeee" + "fffffffffffff" + + "ggggggggggggggggg" + + "hhhhhhhhhhhhhhh" + "iiiiiiiiiiiiiiii" + + "jjjjjjjjjjjjjjjjjjjjjjj"); + } + }; + } +} diff --git a/org.eclipse.jdt.core.tests.model/workspace/Formatter/test549436/E_out.java b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test549436/E_out.java new file mode 100644 index 0000000000..e85dcf7b44 --- /dev/null +++ b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test549436/E_out.java @@ -0,0 +1,88 @@ +public class Example { + String s = """ + aaa + + bbb + + + ccc + """; + + String s2 = """ + aaa + + bbb + + + ccc""" + Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, + 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5); + + Object[] s3 = { "aaaa", """ + bbb + + ccc + + + ddd + """, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, + 7, 8, 9, 0, 1, 2, 3, 4, 5 }; + + Object[] s4 = { "aaaa", // + """ + bbb + + ccc + + + ddd + """, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, + 2, 3, 4, 5 }; + + void foo() { + Arrays.asList(""" + """, """ + 1""", """ + 2 + """, // + "", """ + + + + """, /**/ + """ + aaa + """); + + Object o = new Object(""" + a,b,c,d""".split(""" + ,""")) { + { + System.out.println(""" + aaaaaaaaaaaaaaa + + bbbbbbbbbbbbbb"""); + } + + String bar(boolean arg) { + return (arg ? """ + aaaa + """ : """ + bbb + """) + (arg + ? "cccccccccc" + "ddddddddddd" + "eeeeeeeeee" + + "fffffffffff" + "ggggggggg" + """ + hhhhhhhh""" + : """ + aaaaaaaaa""" + """ + bbbbbbbbb""" + """ + cccccccccccc""" + + """ + ddddddddddddd + """ + "eeeeeeee" + "fffffffffffff" + + "ggggggggggggggggg" + "hhhhhhhhhhhhhhh" + + "iiiiiiiiiiiiiiii" + + "jjjjjjjjjjjjjjjjjjjjjjj"); + } + }; + } +} diff --git a/org.eclipse.jdt.core.tests.model/workspace/Formatter/test549436/F_out.java b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test549436/F_out.java new file mode 100644 index 0000000000..c748510e5e --- /dev/null +++ b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test549436/F_out.java @@ -0,0 +1,87 @@ +public class Example { + String s = """ + aaa + + bbb + + + ccc + """; + + String s2 = """ + aaa + + bbb + + + ccc""" + Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, + 7, 8, 9, 0, 1, 2, 3, 4, 5); + + Object[] s3 = { "aaaa", """ + bbb + + ccc + + + ddd + """, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, + 3, 4, 5 }; + + Object[] s4 = { "aaaa", // + """ + bbb + + ccc + + + ddd + """, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, + 1, 2, 3, 4, 5 }; + + void foo() { + Arrays.asList(""" + """, """ + 1""", """ + 2 + """, // + "", """ + + + + """, /**/ + """ + aaa + """); + + Object o = new Object(""" + a,b,c,d""".split(""" + ,""")) { + { + System.out.println(""" + aaaaaaaaaaaaaaa + + bbbbbbbbbbbbbb"""); + } + + String bar(boolean arg) { + return (arg ? """ + aaaa + """ : """ + bbb + """) + (arg + ? "cccccccccc" + "ddddddddddd" + "eeeeeeeeee" + + "fffffffffff" + "ggggggggg" + """ + hhhhhhhh""" + : """ + aaaaaaaaa""" + """ + bbbbbbbbb""" + """ + cccccccccccc""" + """ + ddddddddddddd + """ + "eeeeeeee" + "fffffffffffff" + + "ggggggggggggggggg" + "hhhhhhhhhhhhhhh" + + "iiiiiiiiiiiiiiii" + + "jjjjjjjjjjjjjjjjjjjjjjj"); + } + }; + } +} diff --git a/org.eclipse.jdt.core.tests.model/workspace/Formatter/test549436/G_out.java b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test549436/G_out.java new file mode 100644 index 0000000000..9405e2564d --- /dev/null +++ b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test549436/G_out.java @@ -0,0 +1,87 @@ +public class Example { + String s = """ + aaa + + bbb + + + ccc + """; + + String s2 = """ + aaa + + bbb + + + ccc""" + Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, + 6, 7, 8, 9, 0, 1, 2, 3, 4, 5); + + Object[] s3 = { "aaaa", """ + bbb + + ccc + + + ddd + """, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, + 2, 3, 4, 5 }; + + Object[] s4 = { "aaaa", // + """ + bbb + + ccc + + + ddd + """, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, + 9, 0, 1, 2, 3, 4, 5 }; + + void foo() { + Arrays.asList(""" + """, """ + 1""", """ + 2 + """, // + "", """ + + + + """, /**/ + """ + aaa + """); + + Object o = new Object(""" + a,b,c,d""".split(""" + ,""")) { + { + System.out.println(""" + aaaaaaaaaaaaaaa + + bbbbbbbbbbbbbb"""); + } + + String bar(boolean arg) { + return (arg ? """ + aaaa + """ : """ + bbb + """) + (arg + ? "cccccccccc" + "ddddddddddd" + "eeeeeeeeee" + + "fffffffffff" + "ggggggggg" + """ + hhhhhhhh""" + : """ + aaaaaaaaa""" + """ + bbbbbbbbb""" + """ + cccccccccccc""" + """ + ddddddddddddd + """ + "eeeeeeee" + "fffffffffffff" + + "ggggggggggggggggg" + "hhhhhhhhhhhhhhh" + + "iiiiiiiiiiiiiiii" + + "jjjjjjjjjjjjjjjjjjjjjjj"); + } + }; + } +} diff --git a/org.eclipse.jdt.core.tests.model/workspace/Formatter/test549436/H_out.java b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test549436/H_out.java new file mode 100644 index 0000000000..1bf3f50d5d --- /dev/null +++ b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test549436/H_out.java @@ -0,0 +1,87 @@ +public class Example { + String s = """ + aaa + + bbb + + + ccc + """; + + String s2 = """ + aaa + + bbb + + + ccc""" + Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, + 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5); + + Object[] s3 = { "aaaa", """ + bbb + + ccc + + + ddd + """, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, + 1, 2, 3, 4, 5 }; + + Object[] s4 = { "aaaa", // + """ + bbb + + ccc + + + ddd + """, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, + 8, 9, 0, 1, 2, 3, 4, 5 }; + + void foo() { + Arrays.asList(""" + """, """ + 1""", """ + 2 + """, // + "", """ + + + + """, /**/ + """ + aaa + """); + + Object o = new Object(""" + a,b,c,d""".split(""" + ,""")) { + { + System.out.println(""" + aaaaaaaaaaaaaaa + + bbbbbbbbbbbbbb"""); + } + + String bar(boolean arg) { + return (arg ? """ + aaaa + """ : """ + bbb + """) + (arg + ? "cccccccccc" + "ddddddddddd" + "eeeeeeeeee" + + "fffffffffff" + "ggggggggg" + """ + hhhhhhhh""" + : """ + aaaaaaaaa""" + """ + bbbbbbbbb""" + """ + cccccccccccc""" + """ + ddddddddddddd + """ + "eeeeeeee" + "fffffffffffff" + + "ggggggggggggggggg" + + "hhhhhhhhhhhhhhh" + "iiiiiiiiiiiiiiii" + + "jjjjjjjjjjjjjjjjjjjjjjj"); + } + }; + } +} diff --git a/org.eclipse.jdt.core.tests.model/workspace/Formatter/test549436/I_out.java b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test549436/I_out.java new file mode 100644 index 0000000000..a46ed3b01a --- /dev/null +++ b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test549436/I_out.java @@ -0,0 +1,88 @@ +public class Example { + String s = """ + aaa + + bbb + + + ccc + """; + + String s2 = """ + aaa + + bbb + + + ccc""" + Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, + 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5); + + Object[] s3 = { "aaaa", """ + bbb + + ccc + + + ddd + """, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, + 7, 8, 9, 0, 1, 2, 3, 4, 5 }; + + Object[] s4 = { "aaaa", // + """ + bbb + + ccc + + + ddd + """, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, + 2, 3, 4, 5 }; + + void foo() { + Arrays.asList(""" + """, """ + 1""", """ + 2 + """, // + "", """ + + + + """, /**/ + """ + aaa + """); + + Object o = new Object(""" + a,b,c,d""".split(""" + ,""")) { + { + System.out.println(""" + aaaaaaaaaaaaaaa + + bbbbbbbbbbbbbb"""); + } + + String bar(boolean arg) { + return (arg ? """ + aaaa + """ : """ + bbb + """) + (arg + ? "cccccccccc" + "ddddddddddd" + "eeeeeeeeee" + + "fffffffffff" + "ggggggggg" + """ + hhhhhhhh""" + : """ + aaaaaaaaa""" + """ + bbbbbbbbb""" + """ + cccccccccccc""" + + """ + ddddddddddddd + """ + "eeeeeeee" + "fffffffffffff" + + "ggggggggggggggggg" + "hhhhhhhhhhhhhhh" + + "iiiiiiiiiiiiiiii" + + "jjjjjjjjjjjjjjjjjjjjjjj"); + } + }; + } +} diff --git a/org.eclipse.jdt.core.tests.model/workspace/Formatter/test549436/J_out.java b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test549436/J_out.java new file mode 100644 index 0000000000..02e03da148 --- /dev/null +++ b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test549436/J_out.java @@ -0,0 +1,88 @@ +public class Example { + String s = """ + aaa + + bbb + + + ccc + """; + + String s2 = """ + aaa + + bbb + + + ccc""" + Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, + 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5); + + Object[] s3 = { "aaaa", """ + bbb + + ccc + + + ddd + """, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, + 7, 8, 9, 0, 1, 2, 3, 4, 5 }; + + Object[] s4 = { "aaaa", // + """ + bbb + + ccc + + + ddd + """, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, + 2, 3, 4, 5 }; + + void foo() { + Arrays.asList(""" + """, """ + 1""", """ + 2 + """, // + "", """ + + + + """, /**/ + """ + aaa + """); + + Object o = new Object(""" + a,b,c,d""".split(""" + ,""")) { + { + System.out.println(""" + aaaaaaaaaaaaaaa + + bbbbbbbbbbbbbb"""); + } + + String bar(boolean arg) { + return (arg ? """ + aaaa + """ : """ + bbb + """) + (arg + ? "cccccccccc" + "ddddddddddd" + "eeeeeeeeee" + + "fffffffffff" + "ggggggggg" + """ + hhhhhhhh""" + : """ + aaaaaaaaa""" + """ + bbbbbbbbb""" + """ + cccccccccccc""" + + """ + ddddddddddddd + """ + "eeeeeeee" + "fffffffffffff" + + "ggggggggggggggggg" + "hhhhhhhhhhhhhhh" + + "iiiiiiiiiiiiiiii" + + "jjjjjjjjjjjjjjjjjjjjjjj"); + } + }; + } +} diff --git a/org.eclipse.jdt.core.tests.model/workspace/Formatter/test549436/K_out.java b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test549436/K_out.java new file mode 100644 index 0000000000..2dcea0b586 --- /dev/null +++ b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test549436/K_out.java @@ -0,0 +1,88 @@ +public class Example { + String s = """ + aaa + + bbb + + + ccc + """; + + String s2 = """ + aaa + + bbb + + + ccc""" + Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, + 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5); + + Object[] s3 = { "aaaa", """ + bbb + + ccc + + + ddd + """, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, + 7, 8, 9, 0, 1, 2, 3, 4, 5 }; + + Object[] s4 = { "aaaa", // + """ + bbb + + ccc + + + ddd + """, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, + 2, 3, 4, 5 }; + + void foo() { + Arrays.asList(""" + """, """ + 1""", """ + 2 + """, // + "", """ + + + + """, /**/ + """ + aaa + """); + + Object o = new Object(""" + a,b,c,d""".split(""" + ,""")) { + { + System.out.println(""" + aaaaaaaaaaaaaaa + + bbbbbbbbbbbbbb"""); + } + + String bar(boolean arg) { + return (arg ? """ + aaaa + """ : """ + bbb + """) + (arg + ? "cccccccccc" + "ddddddddddd" + "eeeeeeeeee" + + "fffffffffff" + "ggggggggg" + """ + hhhhhhhh""" + : """ + aaaaaaaaa""" + """ + bbbbbbbbb""" + """ + cccccccccccc""" + + """ + ddddddddddddd + """ + "eeeeeeee" + "fffffffffffff" + + "ggggggggggggggggg" + "hhhhhhhhhhhhhhh" + + "iiiiiiiiiiiiiiii" + + "jjjjjjjjjjjjjjjjjjjjjjj"); + } + }; + } +} diff --git a/org.eclipse.jdt.core.tests.model/workspace/Formatter/test549436/in.java b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test549436/in.java new file mode 100644 index 0000000000..db75fb0742 --- /dev/null +++ b/org.eclipse.jdt.core.tests.model/workspace/Formatter/test549436/in.java @@ -0,0 +1,79 @@ +public class Example { + String s = """ +aaa + +bbb + + +ccc +"""; + + String s2 = """ + aaa + + bbb + + + ccc""" + Arrays.asList(1, 2 , 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5); + + Object[] s3 = { "aaaa", """ + bbb + + ccc + + + ddd + """, 1, 2 , 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5 }; + + Object[] s4 = { "aaaa", // + """ + bbb + + ccc + + + ddd + """, 1, 2 , 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5 }; + + void foo() { + Arrays.asList(""" + """, + """ + 1""",""" + 2 + """, // + "", """ + + + + """, /**/ +""" +aaa + """); + + Object o = new Object(""" + a,b,c,d""".split(""" + ,""")) { + { +System.out.println(""" + aaaaaaaaaaaaaaa + + bbbbbbbbbbbbbb"""); + } + String bar (boolean arg) { + return (arg ? """ + aaaa + """ : """ + bbb + """) + (arg ? "cccccccccc" + "ddddddddddd" + "eeeeeeeeee" + + "fffffffffff" + "ggggggggg" + """ + hhhhhhhh""" : """ + aaaaaaaaa""" + """ + bbbbbbbbb""" + """ + cccccccccccc""" + """ + ddddddddddddd + """ + "eeeeeeee" + "fffffffffffff" + "ggggggggggggggggg" + "hhhhhhhhhhhhhhh" + "iiiiiiiiiiiiiiii" + "jjjjjjjjjjjjjjjjjjjjjjj"); + } + }; + } +} 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 1481eac39f..f8c6688338 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 @@ -1892,6 +1892,20 @@ public class DefaultCodeFormatterConstants { public static final String FORMATTER_INDENTATION_SIZE = JavaCore.PLUGIN_ID + ".formatter.indentation.size"; //$NON-NLS-1$ /** + * FORMATTER / Option to specify how text blocks are indented + * - option id: "org.eclipse.jdt.core.formatter.text_block_indentation" + * - possible values: { INDENT_PRESERVE, INDENT_BY_ONE, INDENT_DEFAULT, INDENT_ON_COLUMN } + * - default: INDENT_DEFAULT + * </pre> + * @see #INDENT_PRESERVE + * @see #INDENT_BY_ONE + * @see #INDENT_DEFAULT + * @see #INDENT_ON_COLUMN + * @since 3.19 + */ + public static final String FORMATTER_TEXT_BLOCK_INDENTATION = JavaCore.PLUGIN_ID + ".formatter.text_block_indentation"; //$NON-NLS-1$ + + /** * <pre> * FORMATTER / Option to insert a new line after an annotation * - option id: "org.eclipse.jdt.core.formatter.insert_new_line_after_annotation" @@ -5060,6 +5074,13 @@ public class DefaultCodeFormatterConstants { * @since 3.0 */ public static final int INDENT_ON_COLUMN = 1; + /** + * <pre> + * FORMATTER / Indentation is not touched, it's preserved from original source. + * </pre> + * @since 3.19 + */ + public static final int INDENT_PRESERVE = 3; /** * <pre> 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 fbad7115b5..bfa9414b0c 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 @@ -302,7 +302,7 @@ public class DefaultCodeFormatter extends CodeFormatter { resultBuilder.setAlignChar(DefaultCodeFormatterOptions.SPACE); for (Token token : this.tokens) { List<Token> structure = token.getInternalStructure(); - if (structure != null && !structure.isEmpty()) + if (token.isComment() && structure != null && !structure.isEmpty()) resultBuilder.processComment(token); } 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 a51194dec2..1828844fcc 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 @@ -46,6 +46,8 @@ public class DefaultCodeFormatterOptions { public static final int M_FORCE = 1; // if bit set, then alignment will be non-optional (default is optional) public static final int M_INDENT_ON_COLUMN = 2; // if bit set, broken fragments will be aligned on current location column (default is to break at current indentation level) public static final int M_INDENT_BY_ONE = 4; // if bit set, broken fragments will be indented one level below current (not using continuation indentation) + public static final int M_INDENT_DEFAULT = 0; + public static final int M_INDENT_PRESERVE = 8; // split modes can be combined either with M_FORCE or M_INDENT_ON_COLUMN @@ -478,6 +480,7 @@ public class DefaultCodeFormatterOptions { public int page_width; public int tab_char; public boolean use_tabs_only_for_leading_indentations; + public int text_block_indentation; public boolean wrap_before_multiplicative_operator; public boolean wrap_before_additive_operator; public boolean wrap_before_string_concatenation; @@ -869,6 +872,26 @@ public class DefaultCodeFormatterOptions { } options.put(DefaultCodeFormatterConstants.FORMATTER_TAB_SIZE, Integer.toString(this.tab_char == SPACE ? this.indentation_size : this.tab_size)); // reverse values swapping performed by IndentationTabPage options.put(DefaultCodeFormatterConstants.FORMATTER_USE_TABS_ONLY_FOR_LEADING_INDENTATIONS, this.use_tabs_only_for_leading_indentations ? DefaultCodeFormatterConstants.TRUE : DefaultCodeFormatterConstants.FALSE); + + int textBlockIndentation; + switch (this.text_block_indentation) { + case Alignment.M_INDENT_PRESERVE: + textBlockIndentation = DefaultCodeFormatterConstants.INDENT_PRESERVE; + break; + case Alignment.M_INDENT_BY_ONE: + textBlockIndentation = DefaultCodeFormatterConstants.INDENT_BY_ONE; + break; + case Alignment.M_INDENT_DEFAULT: + textBlockIndentation = DefaultCodeFormatterConstants.INDENT_DEFAULT; + break; + case Alignment.M_INDENT_ON_COLUMN: + textBlockIndentation = DefaultCodeFormatterConstants.INDENT_ON_COLUMN; + break; + default: + throw new IllegalArgumentException("Invalid text block indentation: " + this.text_block_indentation); //$NON-NLS-1$ + } + options.put(DefaultCodeFormatterConstants.FORMATTER_TEXT_BLOCK_INDENTATION, Integer.toString(textBlockIndentation)); + options.put(DefaultCodeFormatterConstants.FORMATTER_WRAP_BEFORE_MULTIPLICATIVE_OPERATOR, this.wrap_before_multiplicative_operator ? DefaultCodeFormatterConstants.TRUE : DefaultCodeFormatterConstants.FALSE); options.put(DefaultCodeFormatterConstants.FORMATTER_WRAP_BEFORE_ADDITIVE_OPERATOR, this.wrap_before_additive_operator ? DefaultCodeFormatterConstants.TRUE : DefaultCodeFormatterConstants.FALSE); options.put(DefaultCodeFormatterConstants.FORMATTER_WRAP_BEFORE_STRING_CONCATENATION, this.wrap_before_string_concatenation ? DefaultCodeFormatterConstants.TRUE : DefaultCodeFormatterConstants.FALSE); @@ -2353,6 +2376,19 @@ public class DefaultCodeFormatterOptions { if (useTabsOnlyForLeadingIndentationsOption != null) { this.use_tabs_only_for_leading_indentations = DefaultCodeFormatterConstants.TRUE.equals(useTabsOnlyForLeadingIndentationsOption); } + setInt(settings, DefaultCodeFormatterConstants.FORMATTER_TEXT_BLOCK_INDENTATION, v -> { + if (DefaultCodeFormatterConstants.INDENT_PRESERVE == v) { + this.text_block_indentation = Alignment.M_INDENT_PRESERVE; + } else if (DefaultCodeFormatterConstants.INDENT_BY_ONE == v) { + this.text_block_indentation = Alignment.M_INDENT_BY_ONE; + } else if (DefaultCodeFormatterConstants.INDENT_DEFAULT == v) { + this.text_block_indentation = Alignment.M_INDENT_DEFAULT; + } else if (DefaultCodeFormatterConstants.INDENT_ON_COLUMN == v) { + this.text_block_indentation = Alignment.M_INDENT_ON_COLUMN; + } else { + throw new IllegalArgumentException("invalid text block setting: " + v); //$NON-NLS-1$ + } + }); final Object pageWidthOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_LINE_SPLIT); if (pageWidthOption != null) { try { @@ -3095,6 +3131,7 @@ public class DefaultCodeFormatterOptions { this.page_width = 120; this.tab_char = TAB; // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=49081 this.use_tabs_only_for_leading_indentations = false; + this.text_block_indentation = Alignment.M_INDENT_DEFAULT; this.wrap_before_multiplicative_operator = true; this.wrap_before_additive_operator = true; this.wrap_before_string_concatenation = true; @@ -3457,6 +3494,7 @@ public class DefaultCodeFormatterOptions { this.page_width = 120; this.tab_char = MIXED; this.use_tabs_only_for_leading_indentations = false; + this.text_block_indentation = Alignment.M_INDENT_DEFAULT; this.wrap_before_multiplicative_operator = true; this.wrap_before_additive_operator = true; this.wrap_before_string_concatenation = true; 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 e4cfe2ddd9..01ea65c32a 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 @@ -23,6 +23,7 @@ import static org.eclipse.jdt.internal.compiler.parser.TerminalTokens.TokenNameC import static org.eclipse.jdt.internal.compiler.parser.TerminalTokens.TokenNameLBRACE; import static org.eclipse.jdt.internal.compiler.parser.TerminalTokens.TokenNameRBRACE; import static org.eclipse.jdt.internal.compiler.parser.TerminalTokens.TokenNameSEMICOLON; +import static org.eclipse.jdt.internal.compiler.parser.TerminalTokens.TokenNameTextBlock; import static org.eclipse.jdt.internal.compiler.parser.TerminalTokens.TokenNameelse; import static org.eclipse.jdt.internal.compiler.parser.TerminalTokens.TokenNamefinally; import static org.eclipse.jdt.internal.compiler.parser.TerminalTokens.TokenNamewhile; @@ -70,6 +71,7 @@ import org.eclipse.jdt.core.dom.Statement; import org.eclipse.jdt.core.dom.SwitchCase; import org.eclipse.jdt.core.dom.SwitchExpression; import org.eclipse.jdt.core.dom.SwitchStatement; +import org.eclipse.jdt.core.dom.TextBlock; import org.eclipse.jdt.core.dom.ThrowStatement; import org.eclipse.jdt.core.dom.TryStatement; import org.eclipse.jdt.core.dom.TypeDeclaration; @@ -78,6 +80,9 @@ import org.eclipse.jdt.core.dom.VariableDeclarationStatement; import org.eclipse.jdt.core.dom.WhileStatement; import org.eclipse.jdt.core.dom.YieldStatement; import org.eclipse.jdt.core.formatter.DefaultCodeFormatterConstants; +import org.eclipse.jdt.internal.formatter.DefaultCodeFormatterOptions.Alignment; +import org.eclipse.jdt.internal.formatter.Token.WrapMode; +import org.eclipse.jdt.internal.formatter.Token.WrapPolicy; public class LineBreaksPreparator extends ASTVisitor { final private TokenManager tm; @@ -652,6 +657,56 @@ public class LineBreaksPreparator extends ASTVisitor { return true; } + @Override + public boolean visit(TextBlock node) { + int indentOption = this.options.text_block_indentation; + if (indentOption == Alignment.M_INDENT_PRESERVE) + return true; + Token block = this.tm.firstTokenIn(node, TokenNameTextBlock); + ArrayList<Token> lines = new ArrayList<>(); + lines.add(new Token(block.originalStart, block.originalStart + 2, 0)); // first line; """ + int incidentalWhitespace = Integer.MAX_VALUE; + int blankLines = -1; // will go to 0 on line break after first line + int i = block.originalStart + 3; + while (i <= block.originalEnd) { + int lineStart = i; + int firstNonBlank = -1; + int lastNonBlank = -1; + while (i <= block.originalEnd) { + char c = this.tm.charAt(i++); + if (c == '\r' || c == '\n') { + char c2 = this.tm.charAt(i); + if ((c2 == '\r' || c2 == '\n') && c2 != c) + i++; + break; + } + if (c != ' ' && c != '\t') { + if (firstNonBlank == -1) + firstNonBlank = i - 1; + lastNonBlank = i - 1; + } + } + if (firstNonBlank != -1) { + Token line = new Token(lineStart, lastNonBlank, 0); + line.putLineBreaksBefore(blankLines + 1); + blankLines = 0; + lines.add(line); + incidentalWhitespace = Math.min(incidentalWhitespace, firstNonBlank - lineStart); + } else { + blankLines++; + } + } + WrapPolicy wrapPolicy = new WrapPolicy(WrapMode.DISABLED, 0, -1, 0, 0, 1, false, false); + for (i = 1; i < lines.size(); i++) { + Token t = lines.get(i); + Token line = new Token(t, t.originalStart + incidentalWhitespace, t.originalEnd, TokenNameTextBlock); + line.setWrapPolicy(wrapPolicy); + lines.set(i, line); + } + block.setInternalStructure(lines); + return true; + } + private void breakLineBefore(ASTNode node) { this.tm.firstTokenIn(node, -1).breakBefore(); } diff --git a/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/TextEditsBuilder.java b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/TextEditsBuilder.java index ef25771827..b822e7729e 100644 --- a/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/TextEditsBuilder.java +++ b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/TextEditsBuilder.java @@ -18,6 +18,7 @@ import static org.eclipse.jdt.internal.compiler.parser.TerminalTokens.TokenNameC import static org.eclipse.jdt.internal.compiler.parser.TerminalTokens.TokenNameCOMMENT_JAVADOC; import static org.eclipse.jdt.internal.compiler.parser.TerminalTokens.TokenNameNotAToken; import static org.eclipse.jdt.internal.compiler.parser.TerminalTokens.TokenNameStringLiteral; +import static org.eclipse.jdt.internal.compiler.parser.TerminalTokens.TokenNameTextBlock; import static org.eclipse.jdt.internal.compiler.parser.TerminalTokens.TokenNameWHITESPACE; import java.util.ArrayList; @@ -124,7 +125,7 @@ public class TextEditsBuilder extends TokenTraverser { if (token.tokenType == TokenNameCOMMENT_LINE) { handleSingleLineComment(token, index); } else if (structure != null && !structure.isEmpty()) { - handleMultiLineComment(token, index); + handleStructuredToken(token, index); } else { flushBuffer(token.originalStart); if (token.isToEscape()) { @@ -187,14 +188,17 @@ public class TextEditsBuilder extends TokenTraverser { return; } + boolean isTextBlock = token != null && token.tokenType == TokenNameTextBlock; this.parent.counter = this.counter; this.parent.bufferLineSeparator(null, false); - this.parent.bufferIndent(this.parent.tm.get(this.parentTokenIndex), this.parentTokenIndex); + if (!(isTextBlock && emptyLine && !this.options.indent_empty_lines)) + this.parent.bufferIndent(this.parent.tm.get(this.parentTokenIndex), this.parentTokenIndex); this.counter = this.parent.counter; + if (isTextBlock) + return; if (token != null && token.tokenType == TokenNameNotAToken) return; // this is an unformatted block comment, don't force asterisk - if (getNext() == null && !emptyLine) return; // this is the last token of block comment, asterisk is included @@ -511,7 +515,7 @@ public class TextEditsBuilder extends TokenTraverser { flushBuffer(lineComment.originalEnd + 1); } - private void handleMultiLineComment(Token comment, int index) { + private void handleStructuredToken(Token comment, int index) { flushBuffer(comment.originalStart); if (this.childBuilder == null) { this.childBuilder = new TextEditsBuilder(this); @@ -538,7 +542,7 @@ public class TextEditsBuilder extends TokenTraverser { if (commentToken.tokenType == TokenNameCOMMENT_LINE) { handleSingleLineComment(commentToken, this.tm.indexOf(commentToken)); } else { - handleMultiLineComment(commentToken, this.tm.indexOf(commentToken)); + handleStructuredToken(commentToken, this.tm.indexOf(commentToken)); } } diff --git a/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/TokenManager.java b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/TokenManager.java index f05462943a..071f28286c 100644 --- a/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/TokenManager.java +++ b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/TokenManager.java @@ -13,10 +13,10 @@ *******************************************************************************/ package org.eclipse.jdt.internal.formatter; -import static org.eclipse.jdt.internal.compiler.parser.TerminalTokens.TokenNameCOMMENT_BLOCK; -import static org.eclipse.jdt.internal.compiler.parser.TerminalTokens.TokenNameCOMMENT_JAVADOC; +import static org.eclipse.jdt.internal.compiler.parser.TerminalTokens.TokenNameCOMMENT_LINE; import static org.eclipse.jdt.internal.compiler.parser.TerminalTokens.TokenNameNotAToken; import static org.eclipse.jdt.internal.compiler.parser.TerminalTokens.TokenNameStringLiteral; +import static org.eclipse.jdt.internal.compiler.parser.TerminalTokens.TokenNameTextBlock; import java.util.ArrayList; import java.util.HashMap; @@ -252,9 +252,16 @@ public class TokenManager implements Iterable<Token> { } if (traversed.getAlign() > 0) this.counter = traversed.getAlign(); - List<Token> internalStructure = traversed.getInternalStructure(); - if (internalStructure != null && !internalStructure.isEmpty()) { - assert traversed.tokenType == TokenNameCOMMENT_BLOCK || traversed.tokenType == TokenNameCOMMENT_JAVADOC; + if (traversed.tokenType == TokenNameTextBlock) { + List<Token> lines = traversed.getInternalStructure(); + if (lines == null) { + this.counter = getLength(traversed, 0); + } else { + this.counter = traversed.getIndent() + lines.get(1).getIndent(); + this.counter += getLength(lines.get(lines.size() - 1), this.counter); + } + } else if (traversed.isComment()) { + assert traversed.tokenType != TokenNameCOMMENT_LINE; this.counter = TokenManager.this.commentWrapper.wrapMultiLineComment(traversed, this.counter, true, this.isNLSTagInLine); } else { 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 4da2d1ab29..2fb28a1738 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 @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2014, 2018 Mateusz Matela and others. + * Copyright (c) 2014, 2019 Mateusz Matela and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -18,6 +18,7 @@ package org.eclipse.jdt.internal.formatter.linewrap; import static org.eclipse.jdt.internal.compiler.parser.TerminalTokens.TokenNameCOMMENT_BLOCK; import static org.eclipse.jdt.internal.compiler.parser.TerminalTokens.TokenNameCOMMENT_JAVADOC; import static org.eclipse.jdt.internal.compiler.parser.TerminalTokens.TokenNameCOMMENT_LINE; +import static org.eclipse.jdt.internal.compiler.parser.TerminalTokens.TokenNameTextBlock; import static org.eclipse.jdt.internal.compiler.parser.TerminalTokens.TokenNameWHITESPACE; import java.util.ArrayDeque; @@ -28,6 +29,7 @@ import java.util.List; import org.eclipse.jdt.internal.compiler.parser.ScannerHelper; import org.eclipse.jdt.internal.formatter.DefaultCodeFormatterOptions; +import org.eclipse.jdt.internal.formatter.DefaultCodeFormatterOptions.Alignment; import org.eclipse.jdt.internal.formatter.Token; import org.eclipse.jdt.internal.formatter.TokenManager; import org.eclipse.jdt.internal.formatter.TokenTraverser; @@ -99,13 +101,14 @@ public class WrapExecutor { private class LineAnalyzer extends TokenTraverser { + private final TokenManager tm2 = WrapExecutor.this.tm; private final CommentWrapExecutor commentWrapper; private int lineIndent; int firstPotentialWrap; int activeTopPriorityWrap; int minStructureDepth; int extraLines; - boolean lineExceeded; + int lineWidthExtent; boolean isNextLineWrapped; final List<Integer> extraLinesPerComment = new ArrayList<Integer>(); final List<Integer> topPriorityGroupStarts = new ArrayList<Integer>(); @@ -120,25 +123,28 @@ public class WrapExecutor { * @return index of the last token in line */ public int analyzeLine(int startIndex, int indent) { - Token startToken = WrapExecutor.this.tm.get(startIndex); + Token startToken = this.tm2.get(startIndex); assert startToken.getLineBreaksBefore() > 0; - this.counter = WrapExecutor.this.tm.toIndent(indent, startToken.isWrappable()); + this.counter = this.tm2.toIndent(indent, startToken.isWrappable()); this.lineIndent = indent; this.firstPotentialWrap = -1; this.activeTopPriorityWrap = -1; this.minStructureDepth = Integer.MAX_VALUE; this.extraLines = 0; + this.lineWidthExtent = 0; this.isNextLineWrapped = false; this.extraLinesPerComment.clear(); this.topPriorityGroupStarts.clear(); this.currentTopPriorityGroupEnd = -1; this.isNLSTagInLine = false; - int lastIndex = WrapExecutor.this.tm.traverse(startIndex, this); + int lastIndex = this.tm2.traverse(startIndex, this); return lastIndex + (this.isNextLineWrapped ? 1 : 0); } @Override protected boolean token(Token token, int index) { + setIndent(token, this.lineIndent); + if (token.hasNLSTag()) this.isNLSTagInLine = true; @@ -167,19 +173,30 @@ public class WrapExecutor { this.counter++; } - if (!token.isComment()) { - this.counter += WrapExecutor.this.tm.getLength(token, this.counter); + if (token.tokenType == TokenNameTextBlock) { + List<Token> lines = token.getInternalStructure(); + if (lines == null) { + this.counter = this.tm2.getLength(token, 0); + } else { + this.lineWidthExtent = Math.max(this.lineWidthExtent, + this.counter + this.tm2.getLength(lines.get(0), this.counter)); + this.counter = this.lineIndent + lines.get(1).getIndent(); + lines.stream().skip(1).forEach(e -> this.lineWidthExtent = Math.max(this.lineWidthExtent, + this.counter + this.tm2.getLength(e, this.counter))); + this.counter += this.tm2.getLength(lines.get(lines.size() - 1), this.counter); + } + } else if (!token.isComment()) { + this.counter += this.tm2.getLength(token, this.counter); } else if (token.tokenType != TokenNameCOMMENT_LINE) { this.counter = this.commentWrapper.wrapMultiLineComment(token, this.counter, true, this.isNLSTagInLine); this.extraLines += this.commentWrapper.getLinesCount() - 1; this.extraLinesPerComment.add(this.commentWrapper.getLinesCount() - 1); } - this.lineExceeded = this.counter > WrapExecutor.this.options.page_width; - if (this.lineExceeded && this.firstPotentialWrap >= 0) { + this.lineWidthExtent = Math.max(this.lineWidthExtent, this.counter); + if (this.lineWidthExtent > WrapExecutor.this.options.page_width && this.firstPotentialWrap >= 0) { return false; } - token.setIndent(this.lineIndent); if (getNext() != null && getNext().isWrappable() && getLineBreaksAfter() > 0) { this.isNextLineWrapped = true; @@ -188,9 +205,8 @@ public class WrapExecutor { return false; } - boolean isLineEnd = getLineBreaksAfter() > 0 || getNext() == null - || (getNext().isNextLineOnWrap() && WrapExecutor.this.tm - .get(WrapExecutor.this.tm.findFirstTokenInLine(index)).isWrappable()); + boolean isLineEnd = getLineBreaksAfter() > 0 || getNext() == null || (getNext().isNextLineOnWrap() + && this.tm2.get(this.tm2.findFirstTokenInLine(index)).isWrappable()); return !isLineEnd; } @@ -199,18 +215,14 @@ public class WrapExecutor { return false; for (int i = index - 1; i > wrapPolicy.wrapParentIndex; i--) { - Token token = WrapExecutor.this.tm.get(i); + Token token = this.tm2.get(i); if (token.isWrappable() && token.getWrapPolicy().wrapParentIndex == wrapPolicy.wrapParentIndex - && (token.getLineBreaksBefore() > 0 || WrapExecutor.this.tm.get(i - 1).getLineBreaksAfter() > 0)) { + && (token.getLineBreaksBefore() > 0 || this.tm2.get(i - 1).getLineBreaksAfter() > 0)) { return true; } } return false; } - - public int getLastPosition() { - return this.counter; - } } private class WrapsApplier extends TokenTraverser { @@ -235,7 +247,7 @@ public class WrapExecutor { token.breakBefore(); newLine(token, index); } else { - token.setIndent(this.currentIndent); + setIndent(token, this.currentIndent); } return true; } @@ -244,7 +256,7 @@ public class WrapExecutor { while (!this.stack.isEmpty() && index > this.stack.peek().getWrapPolicy().groupEndIndex) this.stack.pop(); if (token.getWrapPolicy() != null) { - token.setIndent(getWrapIndent(token)); + setIndent(token, getWrapIndent(token)); handleOnColumnIndent(index, token.getWrapPolicy()); this.stack.push(token); } else if (this.stack.isEmpty()) { @@ -253,7 +265,7 @@ public class WrapExecutor { } this.currentIndent = this.stack.isEmpty() ? this.initialIndent : this.stack.peek().getIndent(); - token.setIndent(this.currentIndent); + setIndent(token, this.currentIndent); this.nextWrap = findWrapsCached(index, this.currentIndent).nextWrap; } } @@ -437,8 +449,8 @@ public class WrapExecutor { private WrapResult findWraps(int wrapTokenIndex, int indent) { final int lastIndex = this.lineAnalyzer.analyzeLine(wrapTokenIndex, indent); final boolean nextLineWrapped = this.lineAnalyzer.isNextLineWrapped; - final boolean wrapRequired = this.lineAnalyzer.lineExceeded || nextLineWrapped; - int lineOverflow = Math.max(0, this.lineAnalyzer.getLastPosition() - this.options.page_width); + int lineOverflow = Math.max(0, this.lineAnalyzer.lineWidthExtent - this.options.page_width); + final boolean wrapRequired = lineOverflow > 0 || nextLineWrapped; int extraLines = this.lineAnalyzer.extraLines; final int firstPotentialWrap = this.lineAnalyzer.firstPotentialWrap; final int activeTopPriorityWrap = this.lineAnalyzer.activeTopPriorityWrap; @@ -662,4 +674,25 @@ public class WrapExecutor { wrapIndent += policy.extraIndent; return this.tm.toIndent(wrapIndent, true); } + + void setIndent(Token token, int indent) { + token.setIndent(indent); + + List<Token> structure = token.getInternalStructure(); + if (token.tokenType == TokenNameTextBlock && structure != null) { + int lineIndent; + int indentOption = this.options.text_block_indentation; + if (indentOption == Alignment.M_INDENT_BY_ONE) { + lineIndent = 1 * this.options.indentation_size; + } else if (indentOption == Alignment.M_INDENT_DEFAULT) { + lineIndent = this.options.continuation_indentation * this.options.indentation_size; + } else if (indentOption == Alignment.M_INDENT_ON_COLUMN) { + lineIndent = this.tm.toIndent(this.tm.getPositionInLine(this.tm.indexOf(token)), true) - indent; + } else { + assert false; + lineIndent = 0; + } + structure.stream().skip(1).forEach(t -> t.setIndent(lineIndent)); + } + } } 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 8d4fcaf236..b07e6bae1e 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 @@ -1381,7 +1381,7 @@ public class WrapPreparator extends ASTVisitor { isNLSTagInLine = true; } List<Token> structure = token.getInternalStructure(); - if (structure != null && !structure.isEmpty() && !isNLSTagInLine) { + if (token.isComment() && structure != null && !structure.isEmpty() && !isNLSTagInLine) { int startPosition = this.tm.getPositionInLine(i); if (token.tokenType == TokenNameCOMMENT_LINE) { commentWrapper.wrapLineComment(token, startPosition); |