1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-06-09 10:46:02 +02:00

Formatting of chained conditional expressions and streamlining of formatting code.

This commit is contained in:
Sergey Prigogin 2011-04-07 21:27:36 +00:00
parent 234560eef4
commit 8697be076e
7 changed files with 293 additions and 265 deletions

View file

@ -146,11 +146,22 @@ public class DefaultCodeFormatterConstants {
* FORMATTER / Option for alignment of conditional expression
* - option id: "org.eclipse.cdt.core.formatter.alignment_for_conditional_expression"
* - possible values: values returned by <code>createAlignmentValue(boolean, int, int)</code> call
* - default: createAlignmentValue(false, WRAP_ONE_PER_LINE, INDENT_DEFAULT)
* - default: createAlignmentValue(false, WRAP_COMPACT, INDENT_ON_COLUMN)
* </pre>
* @see #createAlignmentValue(boolean, int, int)
*/
public static final String FORMATTER_ALIGNMENT_FOR_CONDITIONAL_EXPRESSION = CCorePlugin.PLUGIN_ID + ".formatter.alignment_for_conditional_expression"; //$NON-NLS-1$
/**
* <pre>
* FORMATTER / Option for alignment of a chain of conditional expressions.
* - option id: "org.eclipse.cdt.core.formatter.alignment_for_conditional_expression_chain"
* - possible values: values returned by <code>createAlignmentValue(boolean, int, int)</code> call
* - default: createAlignmentValue(false, WRAP_COMPACT, INDENT_ON_COLUMN)
* </pre>
* @see #createAlignmentValue(boolean, int, int)
* @since 5.3
*/
public static final String FORMATTER_ALIGNMENT_FOR_CONDITIONAL_EXPRESSION_CHAIN = CCorePlugin.PLUGIN_ID + ".formatter.alignment_for_conditional_expression_chain"; //$NON-NLS-1$
/**
* <pre>
* FORMATTER / Option for alignment of a declarator list

View file

@ -172,7 +172,6 @@ public class CodeFormatterVisitor extends ASTVisitor implements ICPPASTVisitor,
private static class ListOptions {
final int fMode;
int fSeparatorToken = Token.tCOMMA;
boolean fInsertNewLineBeforeListIfNecessary;
boolean fSpaceBeforeSeparator;
boolean fSpaceAfterSeparator = true;
boolean fSpaceAfterOpeningParen;
@ -1223,6 +1222,7 @@ public class CodeFormatterVisitor extends ASTVisitor implements ICPPASTVisitor,
final ListOptions options= new ListOptions(Alignment.M_COMPACT_SPLIT);
options.fSpaceAfterSeparator= preferences.insert_space_after_comma_in_template_parameters;
options.fSpaceBeforeSeparator= preferences.insert_space_before_comma_in_template_parameters;
options.fTieBreakRule = Alignment.R_OUTERMOST;
formatList(Arrays.asList(templateParameters), options, false, false, null);
}
scribe.printNextToken(new int[] { Token.tGT, Token.tSHIFTR }, preferences.insert_space_before_closing_angle_bracket_in_template_parameters);
@ -1485,7 +1485,6 @@ public class CodeFormatterVisitor extends ASTVisitor implements ICPPASTVisitor,
private ListOptions createListOptionsForFunctionDeclarationParameters() {
final ListOptions options= new ListOptions(preferences.alignment_for_parameters_in_method_declaration);
options.fInsertNewLineBeforeListIfNecessary= true;
options.fSpaceBeforeOpeningParen= preferences.insert_space_before_opening_paren_in_method_declaration;
options.fSpaceAfterOpeningParen= preferences.insert_space_after_opening_paren_in_method_declaration;
options.fSpaceBeforeClosingParen= preferences.insert_space_before_closing_paren_in_method_declaration;
@ -2031,91 +2030,63 @@ public class CodeFormatterVisitor extends ASTVisitor implements ICPPASTVisitor,
if (options.fSpaceAfterOpeningParen) {
scribe.space();
}
Alignment wrapperAlignment = null;
final int continuationIndentation= options.fContinuationIndentation >= 0 ?
options.fContinuationIndentation : preferences.continuation_indentation;
if (options.fInsertNewLineBeforeListIfNecessary &&
(options.fMode & Alignment.M_INDENT_ON_COLUMN) != 0) {
wrapperAlignment = scribe.createAlignment(
Alignment.COLUMN_WRAPPER,
Alignment.M_COMPACT_FIRST_BREAK_SPLIT,
Alignment.R_INNERMOST,
1,
scribe.scanner.getCurrentPosition(),
continuationIndentation,
false);
scribe.enterAlignment(wrapperAlignment);
}
boolean success = false;
Alignment alignment = scribe.createAlignment(
Alignment.LIST_ELEMENTS_PREFIX +
(elements.isEmpty() ? "ellipsis" : elements.get(0).getClass().getSimpleName()), //$NON-NLS-1$
options.fMode,
options.fTieBreakRule,
elementsLength + (addEllipsis ? 1 : 0),
scribe.scanner.getCurrentPosition(),
continuationIndentation,
false);
scribe.enterAlignment(alignment);
boolean ok = false;
do {
if (wrapperAlignment != null)
scribe.alignFragment(wrapperAlignment, 0);
try {
Alignment alignment = scribe.createAlignment(
Alignment.LIST_ELEMENTS_PREFIX +
(elements.isEmpty() ? "ellipsis" : elements.get(0).getClass().getSimpleName()), //$NON-NLS-1$
options.fMode,
options.fTieBreakRule,
elementsLength + (addEllipsis ? 1 : 0),
scribe.scanner.getCurrentPosition(),
wrapperAlignment == null ? continuationIndentation : 0,
false);
scribe.enterAlignment(alignment);
boolean ok = false;
do {
try {
int i;
for (i = 0; i < elementsLength; i++) {
final IASTNode node= elements.get(i);
if (i < alignment.fragmentCount - 1) {
scribe.setTailFormatter(
new TrailingTokenFormatter(options.fSeparatorToken,
options.fSpaceBeforeSeparator,
options.fSpaceAfterSeparator));
} else {
scribe.setTailFormatter(tailFormatter);
}
scribe.alignFragment(alignment, i);
if (node instanceof ICPPASTConstructorChainInitializer) {
// Constructor chain initializer is a special case.
visit((ICPPASTConstructorChainInitializer) node);
} else {
node.accept(this);
}
if (i < alignment.fragmentCount - 1) {
scribe.runTailFormatter();
}
}
if (addEllipsis) {
if (i > 0) {
scribe.printNextToken(options.fSeparatorToken, options.fSpaceBeforeSeparator);
scribe.printTrailingComment();
}
scribe.alignFragment(alignment, i);
if (i > 0 && options.fSpaceAfterSeparator) {
scribe.space();
}
scribe.printNextToken(Token.tELIPSE);
}
scribe.runTailFormatter();
ok = true;
} catch (AlignmentException e) {
scribe.redoAlignment(e);
} catch (ASTProblemException e) {
int i;
for (i = 0; i < elementsLength; i++) {
final IASTNode node= elements.get(i);
if (i < alignment.fragmentCount - 1) {
scribe.setTailFormatter(
new TrailingTokenFormatter(options.fSeparatorToken,
options.fSpaceBeforeSeparator,
options.fSpaceAfterSeparator));
} else {
scribe.setTailFormatter(tailFormatter);
}
} while (!ok);
scribe.exitAlignment(alignment, true);
success = true;
scribe.alignFragment(alignment, i);
if (node instanceof ICPPASTConstructorChainInitializer) {
// Constructor chain initializer is a special case.
visit((ICPPASTConstructorChainInitializer) node);
} else {
node.accept(this);
}
if (i < alignment.fragmentCount - 1) {
scribe.runTailFormatter();
}
}
if (addEllipsis) {
if (i > 0) {
scribe.printNextToken(options.fSeparatorToken, options.fSpaceBeforeSeparator);
scribe.printTrailingComment();
}
scribe.alignFragment(alignment, i);
if (i > 0 && options.fSpaceAfterSeparator) {
scribe.space();
}
scribe.printNextToken(Token.tELIPSE);
}
scribe.runTailFormatter();
ok = true;
} catch (AlignmentException e) {
if (wrapperAlignment == null)
throw e;
scribe.redoAlignment(e);
} catch (ASTProblemException e) {
}
} while (wrapperAlignment != null && !success);
if (wrapperAlignment != null)
scribe.exitAlignment(wrapperAlignment, true);
} while (!ok);
scribe.exitAlignment(alignment, true);
} else if (tailFormatter != null) {
tailFormatter.run();
}
@ -2180,72 +2151,89 @@ public class CodeFormatterVisitor extends ASTVisitor implements ICPPASTVisitor,
}
private int visit(IASTConditionalExpression node) {
// Count nested conditional expressions.
int numConditions = 0;
for (IASTExpression expression = node; expression instanceof IASTConditionalExpression;
expression = ((IASTConditionalExpression) expression).getNegativeResultExpression()) {
numConditions++;
}
Runnable tailFormatter = scribe.takeTailFormatter();
Alignment alignment = scribe.createAlignment(
Alignment.CONDITIONAL_EXPRESSION_CHAIN,
preferences.alignment_for_conditional_expression_chain,
Alignment.R_OUTERMOST,
numConditions,
scribe.scanner.getCurrentPosition());
scribe.enterAlignment(alignment);
boolean ok = false;
do {
try {
IASTConditionalExpression expression = node;
for (int i = 0; ; i++) {
scribe.alignFragment(alignment, i);
boolean last = i == numConditions - 1;
formatConditionalExpression(expression, last ? tailFormatter : null);
if (last)
break;
expression = (IASTConditionalExpression) expression.getNegativeResultExpression();
}
ok = true;
} catch (AlignmentException e) {
scribe.redoAlignment(e);
}
} while (!ok);
scribe.exitAlignment(alignment, true);
return PROCESS_SKIP;
}
private void formatConditionalExpression(IASTConditionalExpression node, Runnable tailFormatter) {
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();
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);
final IASTExpression positiveExpression = node.getPositiveResultExpression();
final IASTExpression negativeExpression = node.getNegativeResultExpression();
try {
Alignment alignment = scribe.createAlignment(
Alignment.CONDITIONAL_EXPRESSION,
preferences.alignment_for_conditional_expression,
Alignment.R_OUTERMOST,
2,
scribe.scanner.getCurrentPosition(),
0,
false);
Alignment alignment = scribe.createAlignment(
Alignment.CONDITIONAL_EXPRESSION,
preferences.alignment_for_conditional_expression,
Alignment.R_OUTERMOST,
negativeExpression instanceof IASTConditionalExpression ? 1 : 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();
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.enterAlignment(alignment);
boolean ok = false;
do {
try {
scribe.alignFragment(alignment, 0);
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);
return PROCESS_SKIP;
}
if (!(negativeExpression instanceof IASTConditionalExpression)) {
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);
}
private int visit(IASTFunctionCallExpression node) {
Runnable tailFormatter = scribe.takeTailFormatter();
@ -2284,7 +2272,6 @@ public class CodeFormatterVisitor extends ASTVisitor implements ICPPASTVisitor,
}
final ListOptions options= new ListOptions(preferences.alignment_for_arguments_in_method_invocation);
options.fSeparatorToken = Token.tCOMMA;
options.fInsertNewLineBeforeListIfNecessary= true;
options.fSpaceBeforeOpeningParen= preferences.insert_space_before_opening_paren_in_method_invocation;
options.fSpaceAfterOpeningParen= preferences.insert_space_after_opening_paren_in_method_invocation;
options.fSpaceBeforeClosingParen= preferences.insert_space_before_closing_paren_in_method_invocation;
@ -2393,7 +2380,6 @@ public class CodeFormatterVisitor extends ASTVisitor implements ICPPASTVisitor,
do {
try {
scribe.alignFragment(alignment, 0);
node.getInitializerClause().accept(this);
ok = true;
} catch (AlignmentException e) {
@ -2656,7 +2642,7 @@ public class CodeFormatterVisitor extends ASTVisitor implements ICPPASTVisitor,
Alignment expressionAlignment= scribe.createAlignment(
Alignment.ASSIGNMENT_EXPRESSION,
preferences.alignment_for_assignment,
Alignment.R_OUTERMOST,
Alignment.R_INNERMOST,
1,
scribe.scanner.getCurrentPosition());
@ -2717,70 +2703,42 @@ public class CodeFormatterVisitor extends ASTVisitor implements ICPPASTVisitor,
scribe.space();
}
Alignment wrapperAlignment = null;
if ((preferences.alignment_for_overloaded_left_shift_chain & Alignment.M_INDENT_ON_COLUMN) != 0) {
wrapperAlignment = scribe.createAlignment(
Alignment.COLUMN_WRAPPER,
Alignment.M_COMPACT_FIRST_BREAK_SPLIT,
Alignment.R_INNERMOST,
1,
scribe.scanner.getCurrentPosition(),
preferences.continuation_indentation,
false);
scribe.enterAlignment(wrapperAlignment);
}
boolean success = false;
Alignment alignment = scribe.createAlignment(
Alignment.OVERLOADED_LEFT_SHIFT_CHAIN,
preferences.alignment_for_overloaded_left_shift_chain,
Alignment.R_OUTERMOST,
elements.size(),
scribe.scanner.getCurrentPosition(),
preferences.continuation_indentation,
false);
scribe.enterAlignment(alignment);
boolean ok = false;
do {
if (wrapperAlignment != null)
scribe.alignFragment(wrapperAlignment, 0);
try {
Alignment alignment = scribe.createAlignment(
Alignment.OVERLOADED_LEFT_SHIFT_CHAIN,
preferences.alignment_for_overloaded_left_shift_chain,
Alignment.R_OUTERMOST,
elements.size(),
scribe.scanner.getCurrentPosition(),
wrapperAlignment == null ? preferences.continuation_indentation : 0,
false);
scribe.enterAlignment(alignment);
boolean ok = false;
do {
try {
for (int i = 0; i < elements.size(); i++) {
scribe.alignFragment(alignment, i);
int token= peekNextToken();
if (token == Token.tSHIFTL) {
scribe.printNextToken(token, preferences.insert_space_before_binary_operator);
scribe.printTrailingComment();
if (preferences.insert_space_after_binary_operator) {
scribe.space();
}
}
node= elements.get(i);
if (i == alignment.fragmentCount - 1) {
scribe.setTailFormatter(tailFormatter);
}
node.accept(this);
for (int i = 0; i < elements.size(); i++) {
scribe.alignFragment(alignment, i);
int token= peekNextToken();
if (token == Token.tSHIFTL) {
scribe.printNextToken(token, preferences.insert_space_before_binary_operator);
scribe.printTrailingComment();
if (preferences.insert_space_after_binary_operator) {
scribe.space();
}
scribe.runTailFormatter();
ok = true;
} catch (AlignmentException e) {
scribe.redoAlignment(e);
} catch (ASTProblemException e) {
}
} while (!ok);
scribe.exitAlignment(alignment, true);
success = true;
node= elements.get(i);
if (i == alignment.fragmentCount - 1) {
scribe.setTailFormatter(tailFormatter);
}
node.accept(this);
}
scribe.runTailFormatter();
ok = true;
} catch (AlignmentException e) {
if (wrapperAlignment == null)
throw e;
scribe.redoAlignment(e);
} catch (ASTProblemException e) {
}
} while (wrapperAlignment != null && !success);
if (wrapperAlignment != null)
scribe.exitAlignment(wrapperAlignment, true);
} while (!ok);
scribe.exitAlignment(alignment, true);
return PROCESS_SKIP;
}
@ -3365,6 +3323,7 @@ public class CodeFormatterVisitor extends ASTVisitor implements ICPPASTVisitor,
final ListOptions options= new ListOptions(Alignment.M_COMPACT_SPLIT);
options.fSpaceAfterSeparator= preferences.insert_space_after_comma_in_template_arguments;
options.fSpaceBeforeSeparator= preferences.insert_space_before_comma_in_template_arguments;
options.fTieBreakRule = Alignment.R_OUTERMOST;
formatList(Arrays.asList(templateArguments), options, false, false, null);
}
if (peekNextToken() == Token.tSHIFTR) {

View file

@ -59,6 +59,7 @@ public class DefaultCodeFormatterOptions {
public int alignment_for_base_clause_in_type_declaration;
public int alignment_for_binary_expression;
public int alignment_for_compact_if;
public int alignment_for_conditional_expression_chain;
public int alignment_for_conditional_expression;
public int alignment_for_declarator_list;
public int alignment_for_enumerator_list;
@ -275,6 +276,7 @@ public class DefaultCodeFormatterOptions {
options.put(DefaultCodeFormatterConstants.FORMATTER_ALIGNMENT_FOR_BINARY_EXPRESSION, getAlignment(this.alignment_for_binary_expression));
options.put(DefaultCodeFormatterConstants.FORMATTER_ALIGNMENT_FOR_COMPACT_IF, getAlignment(this.alignment_for_compact_if));
options.put(DefaultCodeFormatterConstants.FORMATTER_ALIGNMENT_FOR_CONDITIONAL_EXPRESSION, getAlignment(this.alignment_for_conditional_expression));
options.put(DefaultCodeFormatterConstants.FORMATTER_ALIGNMENT_FOR_CONDITIONAL_EXPRESSION_CHAIN, getAlignment(this.alignment_for_conditional_expression_chain));
options.put(DefaultCodeFormatterConstants.FORMATTER_ALIGNMENT_FOR_DECLARATOR_LIST, getAlignment(this.alignment_for_declarator_list));
options.put(DefaultCodeFormatterConstants.FORMATTER_ALIGNMENT_FOR_ENUMERATOR_LIST, getAlignment(this.alignment_for_enumerator_list));
options.put(DefaultCodeFormatterConstants.FORMATTER_ALIGNMENT_FOR_EXPRESSIONS_IN_INITIALIZER_LIST, getAlignment(this.alignment_for_expressions_in_initializer_list));
@ -528,9 +530,19 @@ public class DefaultCodeFormatterOptions {
try {
this.alignment_for_conditional_expression = Integer.parseInt((String) alignmentForConditionalExpressionOption);
} catch (NumberFormatException e) {
this.alignment_for_conditional_expression = Alignment.M_ONE_PER_LINE_SPLIT;
this.alignment_for_conditional_expression = Alignment.M_COMPACT_SPLIT | Alignment.M_INDENT_ON_COLUMN;
} catch (ClassCastException e) {
this.alignment_for_conditional_expression = Alignment.M_ONE_PER_LINE_SPLIT;
this.alignment_for_conditional_expression = Alignment.M_COMPACT_SPLIT | Alignment.M_INDENT_ON_COLUMN;
}
}
final Object alignmentForConditionalExpressionChainOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_ALIGNMENT_FOR_CONDITIONAL_EXPRESSION_CHAIN);
if (alignmentForConditionalExpressionChainOption != null) {
try {
this.alignment_for_conditional_expression_chain = Integer.parseInt((String) alignmentForConditionalExpressionChainOption);
} catch (NumberFormatException e) {
this.alignment_for_conditional_expression_chain = Alignment.M_COMPACT_SPLIT | Alignment.M_INDENT_ON_COLUMN;
} catch (ClassCastException e) {
this.alignment_for_conditional_expression_chain = Alignment.M_COMPACT_SPLIT | Alignment.M_INDENT_ON_COLUMN;
}
}
final Object alignmentForDeclaratorListOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_ALIGNMENT_FOR_DECLARATOR_LIST);
@ -1484,7 +1496,8 @@ public class DefaultCodeFormatterOptions {
this.alignment_for_base_clause_in_type_declaration = Alignment.M_NEXT_PER_LINE_SPLIT;
this.alignment_for_binary_expression = Alignment.M_COMPACT_SPLIT;
this.alignment_for_compact_if = Alignment.M_COMPACT_SPLIT;
this.alignment_for_conditional_expression = Alignment.M_NEXT_PER_LINE_SPLIT;
this.alignment_for_conditional_expression = Alignment.M_COMPACT_SPLIT | Alignment.M_INDENT_ON_COLUMN;
this.alignment_for_conditional_expression_chain = Alignment.M_COMPACT_SPLIT | Alignment.M_INDENT_ON_COLUMN;
this.alignment_for_declarator_list = Alignment.M_COMPACT_SPLIT;
this.alignment_for_enumerator_list = Alignment.M_ONE_PER_LINE_SPLIT;
this.alignment_for_expressions_in_initializer_list = Alignment.M_COMPACT_SPLIT;

View file

@ -227,9 +227,7 @@ public class Scribe {
}
public void alignFragment(Alignment alignment, int fragmentIndex) {
alignment.fragmentIndex= fragmentIndex;
alignment.checkColumn();
alignment.performFragmentEffect();
alignment.alignFragment(fragmentIndex);
}
public void consumeNextToken() {
@ -577,11 +575,22 @@ public class Scribe {
}
public void handleLineTooLong() {
// Search for closest breakable alignment, using tie break rules
// look for outermost breakable one.
// Search for closest breakable alignment, using tie break rules.
// Look for innermost breakable one.
int relativeDepth= 0;
int outerMostDepth= -1;
Alignment targetAlignment= currentAlignment;
while (targetAlignment != null && targetAlignment.tieBreakRule == Alignment.R_INNERMOST) {
if (targetAlignment.couldBreak()) {
throwAlignmentException(AlignmentException.LINE_TOO_LONG, relativeDepth);
}
targetAlignment= targetAlignment.enclosing;
relativeDepth++;
}
// Look for outermost breakable one.
relativeDepth= 0;
int outerMostDepth= -1;
targetAlignment= currentAlignment;
while (targetAlignment != null) {
if (targetAlignment.tieBreakRule == Alignment.R_OUTERMOST && targetAlignment.couldBreak()) {
outerMostDepth= relativeDepth;
@ -592,7 +601,8 @@ public class Scribe {
if (outerMostDepth >= 0) {
throwAlignmentException(AlignmentException.LINE_TOO_LONG, outerMostDepth);
}
// Look for innermost breakable one
// Look for innermost breakable one but don't stop if we encounter a R_OUTERMOST
// tie-breaking rule.
relativeDepth= 0;
targetAlignment= currentAlignment;
while (targetAlignment != null) {

View file

@ -11,6 +11,8 @@
*******************************************************************************/
package org.eclipse.cdt.internal.formatter.align;
import java.util.Arrays;
import org.eclipse.cdt.internal.formatter.Location;
import org.eclipse.cdt.internal.formatter.Scribe;
@ -23,10 +25,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 CONDITIONAL_EXPRESSION_CHAIN = "conditionalExpressionChain"; //$NON-NLS-1$
public static final String DECLARATION_INITIALIZER = "declarationInitializer"; //$NON-NLS-1$
public static final String DESIGNATED_INITIALIZER = "designatedInitializer"; //$NON-NLS-1$
public static final String EXCEPTION_SPECIFICATION = "exceptionSpecification"; //$NON-NLS-1$
@ -65,7 +66,7 @@ public class Alignment {
// Break management
public int originalIndentationLevel;
public int breakIndentationLevel;
public int shiftBreakIndentationLevel;
public int alternativeBreakIndentationLevel;
public int[] fragmentBreaks;
public boolean wasSplit;
public int currentFragmentStartLine;
@ -146,9 +147,9 @@ public class Alignment {
public int tieBreakRule;
// Alignment effects on a per fragment basis
public static final int BREAK_NOT_ALLOWED = -1;
public static final int NONE = 0;
public static final int BREAK = 1;
public static final int BREAK_NOT_ALLOWED = 2;
public static final int BREAK = 2;
// Chunk kind
public static final int CHUNK_FIELD = 1;
@ -169,6 +170,7 @@ public class Alignment {
this.wasSplit = false;
this.fragmentIndentations = new int[this.fragmentCount];
this.fragmentBreaks = new int[this.fragmentCount];
Arrays.fill(this.fragmentBreaks, (this.mode & M_FORCE) == 0 ? BREAK_NOT_ALLOWED : NONE);
this.currentFragmentStartLine = this.scribe.line;
int currentColumn = this.location.outputColumn;
@ -183,17 +185,14 @@ public class Alignment {
if ((mode & M_INDENT_ON_COLUMN) != 0) {
// Indent broken fragments at next indentation level, based on current column
this.breakIndentationLevel = this.scribe.getNextIndentationLevel(currentColumn);
if (this.breakIndentationLevel == this.location.outputIndentationLevel) {
this.breakIndentationLevel += continuationIndent * indentSize;
}
if (continuationIndent == 0) {
this.fragmentBreaks[0] = BREAK_NOT_ALLOWED;
}
this.alternativeBreakIndentationLevel =
this.location.outputIndentationLevel + continuationIndent * indentSize;
} else {
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);
(this.scribe.currentAlignment.mode & M_INDENT_ON_COLUMN) != 0 &&
this.scribe.currentAlignment.fragmentCount > 1) {
baseIndentationLevel = this.scribe.currentAlignment.breakIndentationLevel;
}
if ((mode & M_INDENT_BY_ONE) != 0) {
// Indent broken fragments exactly one level deeper than current indentation
@ -201,11 +200,12 @@ public class Alignment {
} else {
this.breakIndentationLevel = baseIndentationLevel + continuationIndent * indentSize;
}
this.alternativeBreakIndentationLevel = this.breakIndentationLevel;
}
this.shiftBreakIndentationLevel = this.breakIndentationLevel + indentSize;
// Check for forced alignments
if ((this.mode & M_FORCE) != 0) {
this.fragmentBreaks[this.fragmentIndex] = NONE;
couldBreak();
}
}
@ -289,6 +289,15 @@ public class Alignment {
i = this.fragmentIndex;
do {
if (this.fragmentBreaks[i] == NONE) {
if ((this.mode & M_INDENT_ON_COLUMN) != 0 && i == 0) {
if (this.breakIndentationLevel <= this.alternativeBreakIndentationLevel) {
// Does not make sense to break here unless indentation is reduced.
break;
}
// Change break indentation level and erase previously created breaks.
this.breakIndentationLevel = this.alternativeBreakIndentationLevel;
eraseExistingBreaks(i);
}
this.fragmentBreaks[i] = BREAK;
this.fragmentIndentations[i] = this.breakIndentationLevel;
return wasSplit = true;
@ -308,7 +317,8 @@ public class Alignment {
this.fragmentIndentations[0] = this.breakIndentationLevel;
for (i = 1; i < this.fragmentCount; i++) {
this.fragmentBreaks[i] = BREAK;
this.fragmentIndentations[i] = this.shiftBreakIndentationLevel;
this.fragmentIndentations[i] =
this.breakIndentationLevel + this.scribe.indentationSize;
}
return wasSplit = true;
}
@ -335,7 +345,7 @@ public class Alignment {
* #CCCC);
*/
case M_NEXT_PER_LINE_SPLIT:
if (this.fragmentBreaks[0] == NONE) {
if (this.fragmentBreaks[0] != BREAK) {
if (this.fragmentCount > 1 && this.fragmentBreaks[1] == NONE) {
if ((this.mode & M_INDENT_ON_COLUMN) != 0) {
this.fragmentIndentations[0] = this.breakIndentationLevel;
@ -352,6 +362,15 @@ public class Alignment {
return false; // Cannot split better
}
private void eraseExistingBreaks(int startFragmentIndex) {
for (int j = startFragmentIndex + 1; j < this.fragmentIndentations.length; j++) {
if (this.fragmentBreaks[j] == BREAK) {
this.fragmentBreaks[j] = NONE;
this.fragmentIndentations[j] = 0;
}
}
}
public Alignment getAlignment(String targetName) {
if (targetName.equals(this.name)) return this;
if (this.enclosing == null) return null;
@ -359,7 +378,26 @@ public class Alignment {
return this.enclosing.getAlignment(targetName);
}
// perform alignment effect for current fragment
public void alignFragment(int fragmentIndex) {
this.fragmentIndex= fragmentIndex;
if (this.fragmentBreaks[fragmentIndex] == BREAK_NOT_ALLOWED) {
this.fragmentBreaks[fragmentIndex] = NONE; // Allow line break.
}
switch (this.mode & SPLIT_MASK) {
case Alignment.M_NEXT_PER_LINE_SPLIT:
case Alignment.M_ONE_PER_LINE_SPLIT:
for (int i = fragmentIndex + 1; i < this.fragmentBreaks.length; i++) {
if (this.fragmentBreaks[i] == BREAK_NOT_ALLOWED) {
this.fragmentBreaks[i] = NONE; // Allow line break.
}
}
break;
}
checkColumn();
performFragmentEffect();
}
// Performs alignment effect for current fragment.
public void performFragmentEffect() {
if ((this.mode & M_MULTICOLUMN) == 0) {
switch (this.mode & SPLIT_MASK) {

View file

@ -1137,9 +1137,8 @@ public class CodeFormatterTest extends BaseUITestCase {
//int function_with_a_long_name(int, int);
//
//void test() {
// function_with_a_long_name(function(1000000, 2000000, 3000000, 4000000,
// 5000000),
// 6000000);
// function_with_a_long_name(
// function(1000000, 2000000, 3000000, 4000000, 5000000), 6000000);
//}
public void testFunctionCall_2() throws Exception {
fOptions.put(DefaultCodeFormatterConstants.FORMATTER_TAB_CHAR, CCorePlugin.SPACE);
@ -2089,18 +2088,40 @@ public class CodeFormatterTest extends BaseUITestCase {
//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;
//}
// 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();
}
//int variable_with_a_long_name, another_variable_with_a_long_name;
//
//int variable = variable_with_a_long_name < another_variable_with_a_long_name ?
//variable_with_a_long_name + another_variable_with_a_long_name :
//variable_with_a_long_name * 2 > another_variable_with_a_long_name ?
//variable_with_a_long_name + another_variable_with_a_long_name :
//variable_with_a_long_name - another_variable_with_a_long_name;
//int variable_with_a_long_name, another_variable_with_a_long_name;
//
//int variable =
// variable_with_a_long_name < another_variable_with_a_long_name ?
// variable_with_a_long_name + another_variable_with_a_long_name :
// variable_with_a_long_name * 2 > another_variable_with_a_long_name ?
// variable_with_a_long_name + another_variable_with_a_long_name :
// variable_with_a_long_name - another_variable_with_a_long_name;
public void testConditionalExpressionChain() throws Exception {
fOptions.put(DefaultCodeFormatterConstants.FORMATTER_TAB_CHAR, CCorePlugin.SPACE);
assertFormatterResult();
}
@ -2293,7 +2314,7 @@ 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";
//}
public void testOverloadedLeftShiftChain_4() throws Exception {

View file

@ -116,8 +116,8 @@ public final class CIndenter {
prefBlockIndent= prefBlockIndent();
prefArrayIndent= prefArrayIndent();
prefArrayDeepIndent= prefArrayDeepIndent();
prefTernaryDeepAlign= prefTernaryDeepAlign();
prefTernaryIndent= prefTernaryIndent();
prefTernaryDeepAlign= false;
prefTernaryIndent= prefContinuationIndent();
prefCaseIndent= prefCaseIndent();
prefCaseBlockIndent= prefCaseBlockIndent();
prefAssignmentIndent= prefAssignmentIndent();
@ -183,30 +183,6 @@ public final class CIndenter {
return true;
}
private boolean prefTernaryDeepAlign() {
String option= getCoreFormatterOption(DefaultCodeFormatterConstants.FORMATTER_ALIGNMENT_FOR_CONDITIONAL_EXPRESSION);
try {
return DefaultCodeFormatterConstants.getIndentStyle(option) == DefaultCodeFormatterConstants.INDENT_ON_COLUMN;
} catch (IllegalArgumentException e) {
// ignore and return default
}
return false;
}
private int prefTernaryIndent() {
String option= getCoreFormatterOption(DefaultCodeFormatterConstants.FORMATTER_ALIGNMENT_FOR_CONDITIONAL_EXPRESSION);
try {
if (DefaultCodeFormatterConstants.getIndentStyle(option) == DefaultCodeFormatterConstants.INDENT_BY_ONE)
return 1;
else
return prefContinuationIndent();
} catch (IllegalArgumentException e) {
// ignore and return default
}
return prefContinuationIndent();
}
private int prefCaseIndent() {
if (DefaultCodeFormatterConstants.TRUE.equals(getCoreFormatterOption(DefaultCodeFormatterConstants.FORMATTER_INDENT_SWITCHSTATEMENTS_COMPARE_TO_SWITCH)))
return 1;
@ -1031,7 +1007,7 @@ public final class CIndenter {
return skipToPreviousListItemOrListStart();
}
fPosition= pos;
return skipToStatementStart(danglingElse, false);
return skipToPreviousListItemOrListStart();
case Symbols.TokenQUESTIONMARK:
if (fPrefs.prefTernaryDeepAlign) {
@ -1041,7 +1017,7 @@ public final class CIndenter {
}
return fPosition;
// indentation for blockless introducers:
// Indentation for blockless introducers:
case Symbols.TokenDO:
case Symbols.TokenWHILE:
case Symbols.TokenELSE: