diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/formatter/Scribe.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/formatter/Scribe.java index 714f0c59b56..fc85663b663 100644 --- a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/formatter/Scribe.java +++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/formatter/Scribe.java @@ -507,8 +507,8 @@ public class Scribe { } /** - * Answer next indentation level based on column estimated position (if - * column is not indented, then use indentationLevel) + * Returns next indentation level based on column estimated position (if + * column is not indented, then uses indentationLevel) */ public int getNextIndentationLevel(int someColumn) { int indent= someColumn - 1; diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/formatter/align/Alignment.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/formatter/align/Alignment.java index ca0947990ce..efab363a4da 100644 --- a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/formatter/align/Alignment.java +++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/formatter/align/Alignment.java @@ -68,8 +68,9 @@ public class Alignment { public int shiftBreakIndentationLevel; public int[] fragmentBreaks; public boolean wasSplit; + public int currentFragmentStartLine; - public Scribe scribe; + public final Scribe scribe; /* * Alignment modes @@ -168,14 +169,17 @@ public class Alignment { this.wasSplit = false; this.fragmentIndentations = new int[this.fragmentCount]; this.fragmentBreaks = new int[this.fragmentCount]; + this.currentFragmentStartLine = this.scribe.line; - // Initialize the break indentation level, using modes and continuationIndentationLevel preference - final int indentSize = this.scribe.indentationSize; int currentColumn = this.location.outputColumn; if (currentColumn == 1) { currentColumn = this.location.outputIndentationLevel + 1; } + // Initialize the break indentation level, using modes and continuationIndentationLevel + // preference. + final int indentSize = this.scribe.indentationSize; + if ((mode & M_INDENT_ON_COLUMN) != 0) { // Indent broken fragments at next indentation level, based on current column this.breakIndentationLevel = this.scribe.getNextIndentationLevel(currentColumn); @@ -185,11 +189,18 @@ public class Alignment { if (continuationIndent == 0) { this.fragmentBreaks[0] = BREAK_NOT_ALLOWED; } - } else if ((mode & M_INDENT_BY_ONE) != 0) { - // Indent broken fragments exactly one level deeper than current indentation - this.breakIndentationLevel = this.location.outputIndentationLevel + indentSize; } else { - this.breakIndentationLevel = this.location.outputIndentationLevel + continuationIndent * indentSize; + int baseIndentationLevel = this.location.outputIndentationLevel; + if (name != TRAILING_TEXT && this.scribe.currentAlignment != null && + (this.scribe.currentAlignment.mode & M_INDENT_ON_COLUMN) != 0) { + baseIndentationLevel = this.scribe.getNextIndentationLevel(currentColumn); + } + if ((mode & M_INDENT_BY_ONE) != 0) { + // Indent broken fragments exactly one level deeper than current indentation + this.breakIndentationLevel = baseIndentationLevel + indentSize; + } else { + this.breakIndentationLevel = baseIndentationLevel + continuationIndent * indentSize; + } } this.shiftBreakIndentationLevel = this.breakIndentationLevel + indentSize; @@ -203,7 +214,7 @@ public class Alignment { if (this.chunkKind != kind) { this.chunkKind = kind; - // when redoing same chunk alignment, must not reset + // When redoing same chunk alignment, must not reset if (startIndex != this.chunkStartIndex) { this.chunkStartIndex = startIndex; this.location.update(this.scribe, sourceRestart); @@ -216,7 +227,7 @@ public class Alignment { public void checkColumn() { if ((this.mode & M_MULTICOLUMN) != 0) { - int currentIndentation = this.scribe.getNextIndentationLevel(this.scribe.column+(this.scribe.needSpace ? 1 : 0)); + int currentIndentation = this.scribe.getNextIndentationLevel(this.scribe.column + (this.scribe.needSpace ? 1 : 0)); int fragmentIndentation = this.fragmentIndentations[this.fragmentIndex]; if (currentIndentation > fragmentIndentation) { this.fragmentIndentations[this.fragmentIndex] = currentIndentation; @@ -227,7 +238,7 @@ public class Alignment { this.needRedoColumnAlignment = true; } } - // backtrack only once all fragments got checked + // Backtrack only once all fragments got checked if (this.needRedoColumnAlignment && this.fragmentIndex == this.fragmentCount - 1) { // alignment too small // if (CodeFormatterVisitor.DEBUG) { // System.out.println("ALIGNMENT TOO SMALL"); @@ -338,7 +349,7 @@ public class Alignment { } break; } - return false; // cannot split better + return false; // Cannot split better } public Alignment getAlignment(String targetName) { @@ -362,13 +373,21 @@ public class Alignment { return; } } - + + if ((this.mode & M_INDENT_ON_COLUMN) != 0 && this.fragmentIndex > 0 && + this.scribe.line > currentFragmentStartLine) { + // The previous fragment spans multiple line. Put the current fragment on a new line. + this.fragmentBreaks[this.fragmentIndex] = BREAK; + this.fragmentIndentations[this.fragmentIndex] = this.breakIndentationLevel; + wasSplit = true; + } if (this.fragmentBreaks[this.fragmentIndex] == BREAK) { this.scribe.startNewLine(); } if (this.fragmentIndentations[this.fragmentIndex] > 0) { this.scribe.indentationLevel = this.fragmentIndentations[this.fragmentIndex]; } + currentFragmentStartLine = this.scribe.line; } // test whether this is an 'indent-on-column' type alignment and aligns on the given column diff --git a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/CodeFormatterTest.java b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/CodeFormatterTest.java index 51a7db485e2..03b146dc723 100644 --- a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/CodeFormatterTest.java +++ b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/CodeFormatterTest.java @@ -1138,7 +1138,8 @@ public class CodeFormatterTest extends BaseUITestCase { // //void test() { // function_with_a_long_name(function(1000000, 2000000, 3000000, 4000000, - // 5000000), 6000000); + // 5000000), + // 6000000); //} public void testFunctionCall_2() throws Exception { fOptions.put(DefaultCodeFormatterConstants.FORMATTER_TAB_CHAR, CCorePlugin.SPACE); @@ -1158,8 +1159,8 @@ public class CodeFormatterTest extends BaseUITestCase { //int function_with_a_looooooooooooooooooooooooooooooooong_name(int); // //void test() { - // function(function_with_a_looooooooooooooooooooooooooooooooong_name( - // 1000000)); + // function( + // function_with_a_looooooooooooooooooooooooooooooooong_name(1000000)); //} public void testFunctionCall_3() throws Exception { fOptions.put(DefaultCodeFormatterConstants.FORMATTER_TAB_CHAR, CCorePlugin.SPACE); @@ -2271,6 +2272,7 @@ public class CodeFormatterTest extends BaseUITestCase { //class Stream { //Stream& operator<<(const char* s); + //Stream& operator<<(int i); //}; // //Stream stream; @@ -2283,6 +2285,7 @@ public class CodeFormatterTest extends BaseUITestCase { //class Stream { // Stream& operator<<(const char* s); + // Stream& operator<<(int i); //}; // //Stream stream; @@ -2290,11 +2293,10 @@ public class CodeFormatterTest extends BaseUITestCase { // //void test() { // stream << (variable_with_a_long_name + another_variable_with_a_long_name) - // * variable_with_a_long_name + // * variable_with_a_long_name // << "01234567890123456789"; //} - // TODO(sprigogin): Enable the test when the formatter is fixed. - public void _testOverloadedLeftShiftChain_4() throws Exception { + public void testOverloadedLeftShiftChain_4() throws Exception { fOptions.put(DefaultCodeFormatterConstants.FORMATTER_TAB_CHAR, CCorePlugin.SPACE); fOptions.put(DefaultCodeFormatterConstants.FORMATTER_ALIGNMENT_FOR_OVERLOADED_LEFT_SHIFT_CHAIN, Integer.toString(Alignment.M_COMPACT_SPLIT | Alignment.M_INDENT_ON_COLUMN));