diff options
2 files changed, 61 insertions, 23 deletions
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 96e0469d51..3296f5a78f 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 @@ -13036,4 +13036,23 @@ public void testBug551189() { "\n" + "}}"); } +/** + * https://bugs.eclipse.org/220713 - [formatter] Formatting of array initializers in method calls + */ +public void testBug220713() { + this.formatterPrefs.alignment_for_arguments_in_method_invocation = Alignment.M_NEXT_PER_LINE_SPLIT | Alignment.M_INDENT_ON_COLUMN | Alignment.M_FORCE; + this.formatterPrefs.alignment_for_expressions_in_array_initializer = Alignment.M_NEXT_SHIFTED_SPLIT | Alignment.M_INDENT_ON_COLUMN | Alignment.M_FORCE; + this.formatterPrefs.insert_new_line_before_closing_brace_in_array_initializer = true; + formatSource( + "public class A {\n" + + " void f() {\n" + + " methodWithArrays( new Object[] {\n" + + " null,\n" + + " },\n" + + " new Object[] {\n" + + " null,\n" + + " });\n" + + " }\n" + + "}"); +} } 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 2fb28a1738..d3b453f58e 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 @@ -26,15 +26,15 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.LinkedHashSet; import java.util.List; - +import java.util.function.Predicate; 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; import org.eclipse.jdt.internal.formatter.Token.WrapMode; import org.eclipse.jdt.internal.formatter.Token.WrapPolicy; +import org.eclipse.jdt.internal.formatter.TokenManager; +import org.eclipse.jdt.internal.formatter.TokenTraverser; public class WrapExecutor { @@ -227,6 +227,7 @@ public class WrapExecutor { private class WrapsApplier extends TokenTraverser { + private final TokenManager tm2 = WrapExecutor.this.tm; private ArrayDeque<Token> stack = new ArrayDeque<>(); private int initialIndent; private int currentIndent; @@ -242,22 +243,57 @@ public class WrapExecutor { newLine(token, index); } else if ((this.nextWrap != null && index == this.nextWrap.wrapTokenIndex) || checkForceWrap(token, index, this.currentIndent) - || (token.isNextLineOnWrap() && WrapExecutor.this.tm - .get(WrapExecutor.this.tm.findFirstTokenInLine(index)).isWrappable())) { + || (token.isNextLineOnWrap() && this.tm2.get(this.tm2.findFirstTokenInLine(index)).isWrappable())) { token.breakBefore(); newLine(token, index); } else { + checkOnColumnAlign(token, index); setIndent(token, this.currentIndent); } return true; } + private void checkOnColumnAlign(Token token, int index) { + // if some further tokens in a group are wrapped on column, + // the first one should be aligned on column even if it's not wrapped + WrapPolicy wrapPolicy = token.getWrapPolicy(); + if (wrapPolicy == null || !wrapPolicy.indentOnColumn || !wrapPolicy.isFirstInGroup) + return; + int positionInLine = this.tm2.getPositionInLine(index); + if (this.tm2.toIndent(positionInLine, true) == positionInLine) + return; + + Predicate<Token> aligner = t -> { + WrapPolicy wp = t.getWrapPolicy(); + if (wp != null && wp.indentOnColumn && wp.wrapParentIndex == wrapPolicy.wrapParentIndex) { + this.currentIndent = this.tm2.toIndent(positionInLine, true); + token.setAlign(this.currentIndent); + this.stack.push(token); + return true; + } + return false; + }; + + // check all future wraps + WrapInfo furtherWrap = this.nextWrap; + while (furtherWrap != null) { + if (aligner.test(this.tm2.get(furtherWrap.wrapTokenIndex))) + return; + furtherWrap = WrapExecutor.this.wrapSearchResults.get(furtherWrap).nextWrap; + } + // check all tokens that are already wrapped + for (int i = index; i <= wrapPolicy.groupEndIndex; i++) { + Token t = this.tm2.get(i); + if (t.getLineBreaksBefore() > 0 && aligner.test(t)) + return; + } + } + private void newLine(Token token, int index) { while (!this.stack.isEmpty() && index > this.stack.peek().getWrapPolicy().groupEndIndex) this.stack.pop(); if (token.getWrapPolicy() != null) { setIndent(token, getWrapIndent(token)); - handleOnColumnIndent(index, token.getWrapPolicy()); this.stack.push(token); } else if (this.stack.isEmpty()) { this.initialIndent = token.getIndent(); @@ -638,23 +674,6 @@ public class WrapExecutor { return result; } - void handleOnColumnIndent(int tokenIndex, WrapPolicy wrapPolicy) { - if (wrapPolicy != null && wrapPolicy.indentOnColumn && !wrapPolicy.isFirstInGroup - && this.options.tab_char == DefaultCodeFormatterOptions.TAB - && !this.options.use_tabs_only_for_leading_indentations) { - // special case: first wrap in a group should be aligned on column even if it's not wrapped - for (int i = tokenIndex - 1; i >= 0; i--) { - Token token = this.tm.get(i); - WrapPolicy wrapPolicy2 = token.getWrapPolicy(); - if (wrapPolicy2 != null && wrapPolicy2.isFirstInGroup - && wrapPolicy2.wrapParentIndex == wrapPolicy.wrapParentIndex) { - token.setAlign(getWrapIndent(token)); - break; - } - } - } - } - int getWrapIndent(Token token) { WrapPolicy policy = token.getWrapPolicy(); if (policy == null) |