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:
parent
0dcb27b1eb
commit
fbffc783ba
2 changed files with 64 additions and 34 deletions
|
@ -2623,31 +2623,32 @@ 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);
|
|
||||||
scribe.printTrailingComment();
|
|
||||||
|
|
||||||
// In case of macros we may have already passed the operator position.
|
// In case of macros we may have already passed the operator position.
|
||||||
if (scribe.scanner.getCurrentPosition() < node.getOperand2().getFileLocation().getNodeOffset()) {
|
if (i > 0 && scribe.scanner.getCurrentPosition() < operand.getFileLocation().getNodeOffset()) {
|
||||||
scribe.alignFragment(expressionAlignment, 1);
|
scribe.alignFragment(alignment, i);
|
||||||
|
|
||||||
// Operator
|
// Operator
|
||||||
final int nextToken= peekNextToken();
|
final int nextToken= peekNextToken();
|
||||||
// In case of C++ alternative operators, like 'and', 'not', etc. a space
|
// In case of C++ alternative operators, like 'and', 'or', etc. a space
|
||||||
boolean forceSpace= Character.isJavaIdentifierStart(peekNextChar());
|
boolean forceSpace= Character.isJavaIdentifierStart(peekNextChar());
|
||||||
|
|
||||||
switch (node.getOperator()) {
|
switch (node.getOperator()) {
|
||||||
|
@ -2655,29 +2656,58 @@ public class CodeFormatterVisitor extends ASTVisitor implements ICPPASTVisitor,
|
||||||
case IASTBinaryExpression.op_pmarrow:
|
case IASTBinaryExpression.op_pmarrow:
|
||||||
scribe.printNextToken(nextToken, false);
|
scribe.printNextToken(nextToken, false);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
scribe.printNextToken(nextToken, forceSpace || preferences.insert_space_before_binary_operator);
|
scribe.printNextToken(nextToken, forceSpace || preferences.insert_space_before_binary_operator);
|
||||||
if (forceSpace || preferences.insert_space_after_binary_operator) {
|
if (forceSpace || preferences.insert_space_after_binary_operator) {
|
||||||
scribe.space();
|
scribe.space();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
scribe.printTrailingComment();
|
||||||
|
}
|
||||||
|
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();
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Add table
Reference in a new issue