diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/formatter/CodeFormatterVisitor.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/formatter/CodeFormatterVisitor.java index 54a0be73025..a97604222f8 100644 --- a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/formatter/CodeFormatterVisitor.java +++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/formatter/CodeFormatterVisitor.java @@ -205,6 +205,12 @@ public class CodeFormatterVisitor extends ASTVisitor implements ICPPASTVisitor, this.spaceAfterToken = spaceAfterToken; } + TrailingTokenFormatter(int tokenType, IASTNode containingNode, + boolean spaceBeforeToken, boolean spaceAfterToken) { + this(tokenType, findTokenWithinNode(tokenType, containingNode), + spaceBeforeToken, spaceAfterToken); + } + TrailingTokenFormatter(int tokenType, boolean spaceBeforeToken, boolean spaceAfterToken) { this(tokenType, scribe.findToken(tokenType), spaceBeforeToken, spaceAfterToken); } @@ -2032,7 +2038,7 @@ public class CodeFormatterVisitor extends ASTVisitor implements ICPPASTVisitor, if (options.fInsertNewLineBeforeListIfNecessary && (options.fMode & Alignment.M_INDENT_ON_COLUMN) != 0) { wrapperAlignment = scribe.createAlignment( - Alignment.LIST_WRAPPER, + Alignment.COLUMN_WRAPPER, Alignment.M_COMPACT_FIRST_BREAK_SPLIT, Alignment.R_INNERMOST, 1, @@ -2175,61 +2181,70 @@ public class CodeFormatterVisitor extends ASTVisitor implements ICPPASTVisitor, private int visit(IASTConditionalExpression node) { Runnable tailFormatter = scribe.takeTailFormatter(); - try { - node.getLogicalConditionExpression().accept(this); - } finally { - scribe.setTailFormatter(tailFormatter); - } - scribe.printTrailingComment(); - if (preferences.insert_space_before_question_in_conditional) { - scribe.space(); - } - Alignment alignment = scribe.createAlignment( - Alignment.CONDITIONAL_EXPRESSION, - preferences.alignment_for_conditional_expression, - 2, - scribe.scanner.getCurrentPosition()); - scribe.enterAlignment(alignment); - boolean ok = false; - do { - try { - scribe.alignFragment(alignment, 0); - final IASTExpression positiveExpression = node.getPositiveResultExpression(); - final IASTExpression negativeExpression = node.getNegativeResultExpression(); - final IASTExpression nextExpression = positiveExpression != null ? - positiveExpression : negativeExpression; - // In case of macros we may have already passed the question mark position. - if (scribe.scanner.getCurrentPosition() < nextExpression.getFileLocation().getNodeOffset()) { - scribe.printNextToken(Token.tQUESTION, false); - if (preferences.insert_space_after_question_in_conditional) { - scribe.space(); - } - } + scribe.setTailFormatter(new TrailingTokenFormatter(Token.tQUESTION, node, + preferences.insert_space_before_question_in_conditional, + preferences.insert_space_after_question_in_conditional)); + node.getLogicalConditionExpression().accept(this); + scribe.runTailFormatter(); - if (positiveExpression != null) { // gcc-extension allows to omit the positive expression. - positiveExpression.accept(this); - } - scribe.printTrailingComment(); - scribe.alignFragment(alignment, 1); + Alignment wrapperAlignment = scribe.createAlignment( + Alignment.CONDITIONAL_EXPRESSION_WRAPPER, + Alignment.M_COMPACT_FIRST_BREAK_SPLIT, + Alignment.R_OUTERMOST, + 1, + scribe.scanner.getCurrentPosition(), + preferences.continuation_indentation, + false); + scribe.enterAlignment(wrapperAlignment); + boolean success = false; + do { + scribe.alignFragment(wrapperAlignment, 0); - // In case of macros we may have already passed the colon position. - if (scribe.scanner.getCurrentPosition() < negativeExpression.getFileLocation().getNodeOffset()) { - scribe.printNextToken(Token.tCOLON, preferences.insert_space_before_colon_in_conditional); - if (preferences.insert_space_after_colon_in_conditional) { - scribe.space(); - } - } + try { + Alignment alignment = scribe.createAlignment( + Alignment.CONDITIONAL_EXPRESSION, + preferences.alignment_for_conditional_expression, + Alignment.R_OUTERMOST, + 2, + scribe.scanner.getCurrentPosition(), + 0, + false); + + scribe.enterAlignment(alignment); + boolean ok = false; + do { + try { + scribe.alignFragment(alignment, 0); + final IASTExpression positiveExpression = node.getPositiveResultExpression(); + final IASTExpression negativeExpression = node.getNegativeResultExpression(); + scribe.setTailFormatter(new TrailingTokenFormatter(Token.tCOLON, node, + preferences.insert_space_before_colon_in_conditional, + preferences.insert_space_after_colon_in_conditional)); + // A gcc extension allows the positive expression to be omitted. + if (positiveExpression != null) { + positiveExpression.accept(this); + } + scribe.runTailFormatter(); + + scribe.alignFragment(alignment, 1); + scribe.setTailFormatter(tailFormatter); + negativeExpression.accept(this); + scribe.runTailFormatter(); + ok = true; + } catch (AlignmentException e) { + scribe.redoAlignment(e); + } + } while (!ok); + scribe.exitAlignment(alignment, true); + success = true; + } catch (AlignmentException e) { + scribe.redoAlignment(e); + } + } while (!success); + scribe.exitAlignment(wrapperAlignment, true); - negativeExpression.accept(this); - - ok = true; - } catch (AlignmentException e) { - scribe.redoAlignment(e); - } - } while (!ok); - scribe.exitAlignment(alignment, true); - return PROCESS_SKIP; + return PROCESS_SKIP; } private int visit(IASTFunctionCallExpression node) { @@ -2360,31 +2375,32 @@ public class CodeFormatterVisitor extends ASTVisitor implements ICPPASTVisitor, private int visit(IASTEqualsInitializer node) { if (node.getPropertyInParent() == IASTInitializerList.NESTED_INITIALIZER) { assert false; - // nested initializer expression, no need to apply extra alignment + // Nested initializer expression, no need to apply extra alignment // node.getExpression().accept(this); } else { - // declaration initializer - Alignment expressionAlignment= scribe.createAlignment( + // Declaration initializer + Alignment alignment= scribe.createAlignment( Alignment.DECLARATION_INITIALIZER, preferences.alignment_for_assignment, Alignment.R_INNERMOST, 1, scribe.scanner.getCurrentPosition()); - scribe.enterAlignment(expressionAlignment); + Runnable tailFormatter = scribe.getTailFormatter(); + scribe.enterAlignment(alignment); + scribe.setTailFormatter(tailFormatter); // Inherit tail formatter from the enclosing alignment boolean ok = false; do { try { - scribe.alignFragment(expressionAlignment, 0); + scribe.alignFragment(alignment, 0); node.getInitializerClause().accept(this); - ok = true; } catch (AlignmentException e) { scribe.redoAlignment(e); } } while (!ok); - scribe.exitAlignment(expressionAlignment, true); + scribe.exitAlignment(alignment, true); } return PROCESS_SKIP; } @@ -2704,7 +2720,7 @@ public class CodeFormatterVisitor extends ASTVisitor implements ICPPASTVisitor, Alignment wrapperAlignment = null; if ((preferences.alignment_for_overloaded_left_shift_chain & Alignment.M_INDENT_ON_COLUMN) != 0) { wrapperAlignment = scribe.createAlignment( - Alignment.LIST_WRAPPER, + Alignment.COLUMN_WRAPPER, Alignment.M_COMPACT_FIRST_BREAK_SPLIT, Alignment.R_INNERMOST, 1, @@ -2937,10 +2953,12 @@ public class CodeFormatterVisitor extends ASTVisitor implements ICPPASTVisitor, scribe.printNextToken(Token.t_new); scribe.space(); - // placement + // Placement final IASTInitializerClause[] newPlacement= node.getPlacementArguments(); if (newPlacement != null) { + Runnable tailFormatter = scribe.takeTailFormatter(); formatFunctionCallArguments(newPlacement); + scribe.setTailFormatter(tailFormatter); } // type-id @@ -4175,4 +4193,10 @@ public class CodeFormatterVisitor extends ASTVisitor implements ICPPASTVisitor, return node instanceof ICPPASTFunctionDefinition && ((ICPPASTFunctionDefinition) node).getMemberInitializers().length > 0; } + + private int findTokenWithinNode(int tokenType, IASTNode node) { + IASTFileLocation location = node.getFileLocation(); + int endOffset = location.getNodeOffset() + location.getNodeLength(); + return scribe.findToken(tokenType, endOffset); + } } 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 8b87f09d1f2..ca0947990ce 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 @@ -23,7 +23,9 @@ public class Alignment { // Alignment names. public static final String ASSIGNMENT_EXPRESSION = "assignmentExpression"; //$NON-NLS-1$ public static final String BINARY_EXPRESSION = "binaryExpression"; //$NON-NLS-1$ + public static final String COLUMN_WRAPPER = "columnWrapper"; //$NON-NLS-1$ public static final String COMPACT_IF = "compactIf"; //$NON-NLS-1$ + public static final String CONDITIONAL_EXPRESSION_WRAPPER = "conditionalExpressionWrapper"; //$NON-NLS-1$ public static final String CONDITIONAL_EXPRESSION = "conditionalExpression"; //$NON-NLS-1$ public static final String DECLARATION_INITIALIZER = "declarationInitializer"; //$NON-NLS-1$ public static final String DESIGNATED_INITIALIZER = "designatedInitializer"; //$NON-NLS-1$ @@ -31,7 +33,6 @@ public class Alignment { public static final String FIELD_REFERENCE = "fieldReference"; //$NON-NLS-1$ public static final String FOR = "for"; //$NON-NLS-1$ public static final String LIST_ELEMENTS_PREFIX = "listElements_"; //$NON-NLS-1$ - public static final String LIST_WRAPPER = "listWrapper"; //$NON-NLS-1$ public static final String MACRO_ARGUMENTS = "macroArguments"; //$NON-NLS-1$ public static final String OVERLOADED_LEFT_SHIFT_CHAIN = "overloadedLeftShiftChain"; //$NON-NLS-1$ public static final String TRAILING_TEXT = "trailingText"; //$NON-NLS-1$ diff --git a/core/org.eclipse.cdt.ui.tests/resources/formatter/preview/After.cpp b/core/org.eclipse.cdt.ui.tests/resources/formatter/preview/After.cpp index 853c365b125..4f07ae9de88 100644 --- a/core/org.eclipse.cdt.ui.tests/resources/formatter/preview/After.cpp +++ b/core/org.eclipse.cdt.ui.tests/resources/formatter/preview/After.cpp @@ -47,8 +47,8 @@ int foo(int bar) const { int array[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 1000, 2000, 3000, 4000, 5000 }; int compare(int argument, int otherArg) { - return argument + otherArg > argument * otherArg + 1000000 ? 100000 + 50000 - : 200000 - 30000; + return argument + otherArg > argument * otherArg + 1000000 ? + 100000 + 50000 : 200000 - 30000; } class Other { static void bar(int arg1, int arg2, int arg3, int arg4, int arg5, int arg6, 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 886c90479ef..21cf4b6a449 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 @@ -2009,6 +2009,30 @@ public class CodeFormatterTest extends BaseUITestCase { assertFormatterResult(); } + //void test() { + //int variable1 = 1000000 < 2000000 ? 3000000 + 40000000 : 8000000 + 90000000; + //int variable2 = 1000000 < 2000000 ? 3000000 + 40000000 : 8000000 + 900000000; + //int variable3 = 1000000 < 2000000 ? 3000000 + 4000000 + 5000000 + 6000000 + 7000000 : 8000000 + 9000000; + //int variable4 = 1000000 < 2000000 ? 3000000 + 4000000 + 5000000 + 6000000 + 7000000 : 8000000 + 90000000; + //} + + //void test() { + // int variable1 = 1000000 < 2000000 ? 3000000 + 40000000 : 8000000 + 90000000; + // int variable2 = 1000000 < 2000000 ? + // 3000000 + 40000000 : 8000000 + 900000000; + // int variable3 = 1000000 < 2000000 ? + // 3000000 + 4000000 + 5000000 + 6000000 + 7000000 : 8000000 + 9000000; + // int variable4 = 1000000 < 2000000 ? + // 3000000 + 4000000 + 5000000 + 6000000 + 7000000 : + // 8000000 + 90000000; + //} + public void testConditionalExpression() throws Exception { + fOptions.put(DefaultCodeFormatterConstants.FORMATTER_TAB_CHAR, CCorePlugin.SPACE); + fOptions.put(DefaultCodeFormatterConstants.FORMATTER_ALIGNMENT_FOR_CONDITIONAL_EXPRESSION, + Integer.toString(Alignment.M_COMPACT_SPLIT | Alignment.M_INDENT_ON_COLUMN)); + assertFormatterResult(); + } + //// Breaking at '<=' is preferred to breaking at '+'. //bool x = 1000000 + 2000000 + 3000000 + 4000000 <= 5000000 + 6000000 + 7000000 + 8000000;