1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-04-29 19:45:01 +02:00

Bug 367117 - [formatter] cdt hangs when formatting c++ code.

This commit is contained in:
Sergey Prigogin 2011-12-21 10:33:15 -08:00
parent 0dcb27b1eb
commit fbffc783ba
2 changed files with 64 additions and 34 deletions

View file

@ -2623,61 +2623,91 @@ public class CodeFormatterVisitor extends ASTVisitor implements ICPPASTVisitor,
return formatOverloadedLeftShiftChain(node); return formatOverloadedLeftShiftChain(node);
} }
// To improve speed of the algorithm we flatten homogeneous nested binary expressions
// to reduce overall depth of the expression tree.
List<IASTExpression> operands = getOperandsOfMultiExpression(node);
Runnable tailFormatter = endsWithMacroExpansion(node) ? null : scribe.takeTailFormatter(); Runnable tailFormatter = endsWithMacroExpansion(node) ? null : scribe.takeTailFormatter();
Alignment expressionAlignment= scribe.createAlignment( Alignment alignment= scribe.createAlignment(
Alignment.BINARY_EXPRESSION, Alignment.BINARY_EXPRESSION,
preferences.alignment_for_binary_expression, preferences.alignment_for_binary_expression,
Alignment.R_OUTERMOST, Alignment.R_OUTERMOST,
2, operands.size(),
scribe.scanner.getCurrentPosition()); scribe.scanner.getCurrentPosition());
scribe.enterAlignment(expressionAlignment); scribe.enterAlignment(alignment);
boolean ok = false; boolean ok = false;
do { do {
try { try {
final IASTExpression op1= node.getOperand1(); for (int i = 0; i < operands.size(); i++) {
// Left operand final IASTExpression operand = operands.get(i);
op1.accept(this); // In case of macros we may have already passed the operator position.
scribe.printTrailingComment(); if (i > 0 && scribe.scanner.getCurrentPosition() < operand.getFileLocation().getNodeOffset()) {
scribe.alignFragment(alignment, i);
// In case of macros we may have already passed the operator position. // Operator
if (scribe.scanner.getCurrentPosition() < node.getOperand2().getFileLocation().getNodeOffset()) { final int nextToken= peekNextToken();
scribe.alignFragment(expressionAlignment, 1); // In case of C++ alternative operators, like 'and', 'or', etc. a space
boolean forceSpace= Character.isJavaIdentifierStart(peekNextChar());
// Operator switch (node.getOperator()) {
final int nextToken= peekNextToken(); case IASTBinaryExpression.op_pmdot:
// In case of C++ alternative operators, like 'and', 'not', etc. a space case IASTBinaryExpression.op_pmarrow:
boolean forceSpace= Character.isJavaIdentifierStart(peekNextChar()); scribe.printNextToken(nextToken, false);
break;
switch (node.getOperator()) { default:
case IASTBinaryExpression.op_pmdot: scribe.printNextToken(nextToken, forceSpace || preferences.insert_space_before_binary_operator);
case IASTBinaryExpression.op_pmarrow: if (forceSpace || preferences.insert_space_after_binary_operator) {
scribe.printNextToken(nextToken, false); scribe.space();
break; }
default: }
scribe.printNextToken(nextToken, forceSpace || preferences.insert_space_before_binary_operator); scribe.printTrailingComment();
if (forceSpace || preferences.insert_space_after_binary_operator) { }
scribe.space(); if (i == alignment.fragmentCount - 1) {
} scribe.setTailFormatter(tailFormatter);
} }
} operand.accept(this);
scribe.restartAtOffset(getNodeEndLocation(operand));
scribe.printTrailingComment();
}
// Right operand scribe.runTailFormatter();
final IASTExpression op2= node.getOperand2();
op2.accept(this);
if (tailFormatter != null)
tailFormatter.run();
ok = true; ok = true;
} catch (AlignmentException e) { } catch (AlignmentException e) {
scribe.redoAlignment(e); scribe.redoAlignment(e);
} }
} while (!ok); } while (!ok);
scribe.exitAlignment(expressionAlignment, true); scribe.exitAlignment(alignment, true);
return PROCESS_SKIP; return PROCESS_SKIP;
} }
/**
* Traverses a chain of nested homogeneous left-to-right-associative binary expressions and
* returns a list of their operands in left-to-right order. For example, for the expression
* a + b * c + d, it will return a list containing expressions: a, b * c, and d.
*
* @param binaryExpression the top-level binary expression
* @return a list of expression operands from left to right
*/
private List<IASTExpression> getOperandsOfMultiExpression(IASTBinaryExpression binaryExpression) {
int operator = binaryExpression.getOperator();
List<IASTExpression> operands = new ArrayList<IASTExpression>(2);
IASTExpression node;
do {
operands.add(binaryExpression.getOperand2());
node = binaryExpression.getOperand1();
if (!(node instanceof IASTBinaryExpression)) {
break;
}
binaryExpression = (IASTBinaryExpression) node;
} while (binaryExpression.getOperator() == operator);
operands.add(node);
Collections.reverse(operands);
return operands;
}
private int formatAssignment(IASTBinaryExpression node) { private int formatAssignment(IASTBinaryExpression node) {
Runnable tailFormatter = scribe.takeTailFormatter(); Runnable tailFormatter = scribe.takeTailFormatter();
final IASTExpression op1= node.getOperand1(); final IASTExpression op1= node.getOperand1();

View file

@ -311,7 +311,7 @@ public class Alignment {
this.fragmentIndentations[i] = this.breakIndentationLevel; this.fragmentIndentations[i] = this.breakIndentationLevel;
return wasSplit = true; return wasSplit = true;
} }
} while (--i >= 0); } while ((this.fragmentBreaks[i] != BREAK || (this.mode & M_INDENT_ON_COLUMN) != 0) && --i >= 0);
break; break;
/* # aligned fragment /* # aligned fragment