diff options
4 files changed, 101 insertions, 35 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 1fd9b9ac5e..84dab8e485 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 @@ -13126,4 +13126,73 @@ public void testBug560889() { " }\n" + "}"); } +public void testBug563487a() { + formatSource( + "class A {\n" + + " protected void f() {\n" + + " cccccccccccccc\n" + + " // \n" + + " .forEach(c -> {\n" + + " aaaaaa();\n" + + "[# bbbbbb();#]\n" + + " });\n" + + " }\n" + + "}", + "class A {\n" + + " protected void f() {\n" + + " cccccccccccccc\n" + + " // \n" + + " .forEach(c -> {\n" + + " aaaaaa();\n" + + " bbbbbb();\n" + + " });\n" + + " }\n" + + "}"); +} +public void testBug563487b() { + formatSource( + "class A {\n" + + " protected void f() {\n" + + " cccccccccccccc\n" + + " // \n" + + " .forEach(c -> {\n" + + " aaaaaa();\n" + + "[# bbbbbb();#]\n" + + " });\n" + + " }\n" + + "}", + "class A {\n" + + " protected void f() {\n" + + " cccccccccccccc\n" + + " // \n" + + " .forEach(c -> {\n" + + " aaaaaa();\n" + + " bbbbbb();\n" + + " });\n" + + " }\n" + + "}"); +} +public void testBug563487c() { + formatSource( + "class A {\n" + + "protected void f() {\n" + + "cccccccccccccc\n" + + " // \n" + + " .forEach(c -> {\n" + + " aaaaaa();\n" + + "[# bbbbbb();#]\n" + + " });\n" + + "}\n" + + "}", + "class A {\n" + + "protected void f() {\n" + + "cccccccccccccc\n" + + " // \n" + + " .forEach(c -> {\n" + + " aaaaaa();\n" + + " bbbbbb();\n" + + " });\n" + + "}\n" + + "}"); +} } 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 5afa975025..6d94c6824f 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 @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2019 IBM Corporation and others. + * Copyright (c) 2000, 2020 IBM Corporation and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -416,7 +416,7 @@ public class DefaultCodeFormatter extends CodeFormatter { private void prepareLineBreaks() { LineBreaksPreparator breaksPreparator = new LineBreaksPreparator(this.tokenManager, this.workingOptions); this.astRoot.accept(breaksPreparator); - breaksPreparator.finishUp(this.formatRegions); + breaksPreparator.finishUp(); this.astRoot.accept(new OneLineEnforcer(this.tokenManager, this.workingOptions)); } 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 9add4c0db5..d6e62fe30c 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 @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2014, 2019 Mateusz Matela and others. + * Copyright (c) 2014, 2020 Mateusz Matela and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -85,7 +85,6 @@ 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; -import org.eclipse.jface.text.IRegion; public class LineBreaksPreparator extends ASTVisitor { final private TokenManager tm; @@ -808,37 +807,13 @@ public class LineBreaksPreparator extends ASTVisitor { this.tm.get(lastIndex + 1).unindent(); } - public void finishUp(List<IRegion> regions) { + public void finishUp() { // the visits only noted where indents increase and decrease, - // now prepare actual indent values, preserving indents outside formatting regions - int currentIndent = this.options.initial_indentation_level * this.options.indentation_size; - Token previous = null; + // now prepare actual indent values + int currentIndent = this.options.initial_indentation_level; for (Token token : this.tm) { - if (isFixedLineStart(token, previous, regions)) { - currentIndent = this.tm.findSourcePositionInLine(token.originalStart); - } else { - currentIndent = Math.max(currentIndent + token.getIndent() * this.options.indentation_size, 0); - } - token.setIndent(currentIndent); - previous = token; - } - } - - private boolean isFixedLineStart(Token token, Token previous, List<IRegion> regions) { - if (previous == null && this.options.initial_indentation_level >0) - return false; // must be handling ast rewrite - if (previous != null && this.tm.countLineBreaksBetween(previous, token) == 0) - return false; - if (token.getLineBreaksBefore() == 0 && (previous == null || previous.getLineBreaksAfter() == 0)) - return false; - int lineStart = token.originalStart; - char c; - while (lineStart > 0 && (c = this.tm.charAt(lineStart - 1)) != '\r' && c != '\n') - lineStart--; - for (IRegion r : regions) { - if (token.originalStart >= r.getOffset() && lineStart <= r.getOffset() + r.getLength()) - return false; + currentIndent += token.getIndent(); + token.setIndent(currentIndent * this.options.indentation_size); } - 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 276da6c15e..b347880f56 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 @@ -232,6 +232,7 @@ public class WrapExecutor { private ArrayDeque<Token> stack = new ArrayDeque<>(); private int initialIndent; private int currentIndent; + private int fixedIndentDelta; private WrapInfo nextWrap; public WrapsApplier() { @@ -297,7 +298,13 @@ public class WrapExecutor { setIndent(token, getWrapIndent(token)); this.stack.push(token); } else if (this.stack.isEmpty()) { - this.initialIndent = token.getIndent(); + if (isFixedLineStart(token, index)) { + int fixedIndent = this.tm2.findSourcePositionInLine(token.originalStart); + this.initialIndent = fixedIndent; + this.fixedIndentDelta = fixedIndent - token.getIndent(); + } else { + this.initialIndent = Math.max(0, token.getIndent() + this.fixedIndentDelta); + } WrapExecutor.this.wrapSearchResults.clear(); } @@ -305,6 +312,21 @@ public class WrapExecutor { setIndent(token, this.currentIndent); this.nextWrap = findWrapsCached(index, this.currentIndent).nextWrap; } + + private boolean isFixedLineStart(Token token, int index) { + if (WrapExecutor.this.options.initial_indentation_level > 0) + return false; // must be handling ast rewrite + if (index > 0 && this.tm2.countLineBreaksBetween(getPrevious(), token) == 0) + return false; + if (isWrapInsideFormatRegion(index)) + return false; + int start = token.originalStart; + boolean inDisableFormat = this.tm2.getDisableFormatTokenPairs().stream() + .anyMatch(p -> p[0].originalStart <= start && p[1].originalStart >= start); + if (inDisableFormat) + return false; + return true; + } } private class NLSTagHandler extends TokenTraverser { @@ -679,7 +701,7 @@ public class WrapExecutor { } boolean isWrapInsideFormatRegion(int tokenIndex) { - int pos1 = this.tm.get(tokenIndex - 1).originalEnd; + int pos1 = tokenIndex == 0 ? 0 : this.tm.get(tokenIndex - 1).originalEnd; int pos2 = this.tm.get(tokenIndex).originalStart; return this.regions.stream().anyMatch(r -> (pos1 >= r.getOffset() && pos1 < r.getOffset() + r.getLength()) || (pos2 >= r.getOffset() && pos2 < r.getOffset() + r.getLength())); |