mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-04-29 19:45:01 +02:00
Bug 357423 - Code formatter gets confused by a macro. Macro involving an
'if' statement.
This commit is contained in:
parent
1c153dcece
commit
a090d9bd2c
2 changed files with 239 additions and 120 deletions
|
@ -114,6 +114,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTForStatement;
|
|||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionDeclarator;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionDefinition;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionWithTryBlock;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTIfStatement;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTLinkageSpecification;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNamedTypeSpecifier;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNamespaceAlias;
|
||||
|
@ -1658,6 +1659,7 @@ public class CodeFormatterVisitor extends ASTVisitor implements ICPPASTVisitor,
|
|||
Runnable tailFormatter = fExpectSemicolonAfterDeclaration ?
|
||||
new TrailingSemicolonFormatter(node) : null;
|
||||
if (declarators.size() == 1) {
|
||||
if (tailFormatter != null) {
|
||||
scribe.setTailFormatter(tailFormatter);
|
||||
try {
|
||||
visit(declarators.get(0));
|
||||
|
@ -1665,6 +1667,9 @@ public class CodeFormatterVisitor extends ASTVisitor implements ICPPASTVisitor,
|
|||
} finally {
|
||||
scribe.setTailFormatter(null);
|
||||
}
|
||||
} else {
|
||||
visit(declarators.get(0));
|
||||
}
|
||||
} else {
|
||||
final ListOptions options= new ListOptions(preferences.alignment_for_declarator_list);
|
||||
options.fSpaceAfterSeparator= preferences.insert_space_after_comma_in_declarator_list;
|
||||
|
@ -2153,12 +2158,7 @@ public class CodeFormatterVisitor extends ASTVisitor implements ICPPASTVisitor,
|
|||
}
|
||||
final IASTDeclaration decl= node.getDeclaration();
|
||||
if (decl != null) {
|
||||
fExpectSemicolonAfterDeclaration= false;
|
||||
try {
|
||||
decl.accept(this);
|
||||
} finally {
|
||||
fExpectSemicolonAfterDeclaration= true;
|
||||
}
|
||||
formatInlineDeclaration(decl);
|
||||
} else if (node.isCatchAll()) {
|
||||
scribe.printNextToken(Token.tELIPSE, false /* preferences.insert_space_before_ellipsis */);
|
||||
// if (false /* preferences.insert_space_after_ellipsis */) {
|
||||
|
@ -2173,6 +2173,15 @@ public class CodeFormatterVisitor extends ASTVisitor implements ICPPASTVisitor,
|
|||
return PROCESS_SKIP;
|
||||
}
|
||||
|
||||
private void formatInlineDeclaration(final IASTDeclaration decl) {
|
||||
fExpectSemicolonAfterDeclaration= false;
|
||||
try {
|
||||
decl.accept(this);
|
||||
} finally {
|
||||
fExpectSemicolonAfterDeclaration= true;
|
||||
}
|
||||
}
|
||||
|
||||
private int visit(IASTCompoundStatement node) {
|
||||
formatBlock(node, preferences.brace_position_for_block, preferences.insert_space_before_opening_brace_in_block, preferences.indent_statements_compare_to_block);
|
||||
return PROCESS_SKIP;
|
||||
|
@ -3079,14 +3088,29 @@ public class CodeFormatterVisitor extends ASTVisitor implements ICPPASTVisitor,
|
|||
}
|
||||
|
||||
private int visit(IASTForStatement node) {
|
||||
if (!startsWithMacroExpansion(node)) {
|
||||
scribe.printNextToken(Token.t_for);
|
||||
}
|
||||
final int line = scribe.line;
|
||||
IASTStatement initializerStmt= node.getInitializerStatement();
|
||||
IASTStatement body = node.getBody();
|
||||
Runnable tailFormatter = null;
|
||||
if (!doNodesHaveSameOffset(node, initializerStmt)) {
|
||||
scribe.printNextToken(Token.tLPAREN, preferences.insert_space_before_opening_paren_in_for);
|
||||
fInsideFor= true;
|
||||
if (preferences.insert_space_after_opening_paren_in_for) {
|
||||
scribe.space();
|
||||
}
|
||||
IASTStatement initializerStmt= node.getInitializerStatement();
|
||||
if (DefaultCodeFormatterConstants.END_OF_LINE.equals(preferences.brace_position_for_block) &&
|
||||
body instanceof IASTCompoundStatement && !startsWithMacroExpansion(body)) {
|
||||
tailFormatter = new TrailingTokenFormatter(Token.tLBRACE,
|
||||
body.getFileLocation().getNodeOffset(),
|
||||
preferences.insert_space_before_opening_brace_in_block, false);
|
||||
}
|
||||
tailFormatter = new ClosingParensesisTailFormatter(
|
||||
preferences.insert_space_before_closing_paren_in_for, tailFormatter);
|
||||
}
|
||||
|
||||
initializerStmt.accept(this);
|
||||
if (peekNextToken() == Token.tSEMI) {
|
||||
scribe.printNextToken(Token.tSEMI, preferences.insert_space_before_semicolon_in_for);
|
||||
|
@ -3124,6 +3148,7 @@ public class CodeFormatterVisitor extends ASTVisitor implements ICPPASTVisitor,
|
|||
scribe.printNextToken(Token.tSEMI, preferences.insert_space_before_semicolon_in_for);
|
||||
}
|
||||
|
||||
scribe.setTailFormatter(tailFormatter);
|
||||
scribe.alignFragment(alignment, 1);
|
||||
IASTExpression iterationExpr= node.getIterationExpression();
|
||||
if (iterationExpr != null) {
|
||||
|
@ -3132,52 +3157,62 @@ public class CodeFormatterVisitor extends ASTVisitor implements ICPPASTVisitor,
|
|||
}
|
||||
iterationExpr.accept(this);
|
||||
}
|
||||
if (tailFormatter != null) {
|
||||
scribe.runTailFormatter();
|
||||
scribe.setTailFormatter(null);
|
||||
}
|
||||
} finally {
|
||||
fInsideFor= false;
|
||||
}
|
||||
if (peekNextToken() == Token.tRPAREN) {
|
||||
scribe.printNextToken(Token.tRPAREN, preferences.insert_space_before_closing_paren_in_for);
|
||||
ok = true;
|
||||
} catch (AlignmentException e) {
|
||||
scribe.redoAlignment(e);
|
||||
}
|
||||
IASTStatement body = node.getBody();
|
||||
} while (!ok);
|
||||
scribe.exitAlignment(alignment, true);
|
||||
|
||||
if (body instanceof IASTCompoundStatement && !startsWithMacroExpansion(body)) {
|
||||
formatLeftCurlyBrace(line, preferences.brace_position_for_block);
|
||||
// if (body instanceof IASTCompoundStatement && !startsWithMacroExpansion(body)) {
|
||||
// formatLeftCurlyBrace(line, preferences.brace_position_for_block);
|
||||
// if (startNode(body)) {
|
||||
// try {
|
||||
// final boolean braceOnSameLine = DefaultCodeFormatterConstants.END_OF_LINE.equals(preferences.brace_position_for_block);
|
||||
// if (!braceOnSameLine) {
|
||||
// ok = true;
|
||||
// scribe.exitAlignment(alignment, true);
|
||||
// }
|
||||
// formatBlockOpening((IASTCompoundStatement) body,
|
||||
// preferences.brace_position_for_block,
|
||||
// preferences.insert_space_before_opening_brace_in_block);
|
||||
// if (braceOnSameLine) {
|
||||
// ok = true;
|
||||
// scribe.exitAlignment(alignment, true);
|
||||
// }
|
||||
// formatOpenedBlock((IASTCompoundStatement) body,
|
||||
// preferences.brace_position_for_block,
|
||||
// preferences.indent_statements_compare_to_block);
|
||||
// } finally {
|
||||
// endOfNode(body);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
if (startNode(body)) {
|
||||
try {
|
||||
final boolean braceOnSameLine = DefaultCodeFormatterConstants.END_OF_LINE.equals(preferences.brace_position_for_block);
|
||||
if (!braceOnSameLine) {
|
||||
ok = true;
|
||||
scribe.exitAlignment(alignment, true);
|
||||
if (scribe.scanner.getCurrentPosition() <= body.getFileLocation().getNodeOffset()) {
|
||||
formatLeftCurlyBrace(line, preferences.brace_position_for_block);
|
||||
}
|
||||
formatBlockOpening((IASTCompoundStatement) body,
|
||||
preferences.brace_position_for_block,
|
||||
preferences.insert_space_before_opening_brace_in_block);
|
||||
if (braceOnSameLine) {
|
||||
ok = true;
|
||||
scribe.exitAlignment(alignment, true);
|
||||
}
|
||||
formatOpenedBlock((IASTCompoundStatement) body,
|
||||
formatBlock((IASTCompoundStatement) body,
|
||||
preferences.brace_position_for_block,
|
||||
preferences.insert_space_before_opening_brace_in_block,
|
||||
preferences.indent_statements_compare_to_block);
|
||||
} finally {
|
||||
endOfNode(body);
|
||||
}
|
||||
} else {
|
||||
ok = true;
|
||||
scribe.exitAlignment(alignment, true);
|
||||
}
|
||||
} else {
|
||||
ok = true;
|
||||
scribe.exitAlignment(alignment, true);
|
||||
formatAction(line, body, preferences.brace_position_for_block);
|
||||
}
|
||||
} catch (AlignmentException e) {
|
||||
if (ok) {
|
||||
throw e;
|
||||
}
|
||||
scribe.redoAlignment(e);
|
||||
}
|
||||
} while (!ok);
|
||||
|
||||
scribe.printTrailingComment();
|
||||
return PROCESS_SKIP;
|
||||
}
|
||||
|
||||
|
@ -3210,15 +3245,24 @@ public class CodeFormatterVisitor extends ASTVisitor implements ICPPASTVisitor,
|
|||
}
|
||||
|
||||
private int visit(IASTIfStatement node) {
|
||||
if (!startsWithMacroExpansion(node)) {
|
||||
scribe.printNextToken(Token.t_if);
|
||||
}
|
||||
final int line = scribe.line;
|
||||
IASTNode condition = node.getConditionExpression();
|
||||
if (condition == null && node instanceof ICPPASTIfStatement) {
|
||||
condition = ((ICPPASTIfStatement) node).getConditionDeclaration();
|
||||
}
|
||||
final IASTStatement thenStatement = node.getThenClause();
|
||||
final IASTStatement elseStatement = node.getElseClause();
|
||||
|
||||
fExpectSemicolonAfterDeclaration= false;
|
||||
try {
|
||||
if (condition == null || !doNodesHaveSameOffset(node, condition)) {
|
||||
scribe.printNextToken(Token.tLPAREN, preferences.insert_space_before_opening_paren_in_if);
|
||||
if (preferences.insert_space_after_opening_paren_in_if) {
|
||||
scribe.space();
|
||||
}
|
||||
IASTExpression condExpr= node.getConditionExpression();
|
||||
final IASTStatement thenStatement = node.getThenClause();
|
||||
final IASTStatement elseStatement = node.getElseClause();
|
||||
Runnable tailFormatter = null;
|
||||
if (DefaultCodeFormatterConstants.END_OF_LINE.equals(preferences.brace_position_for_block) &&
|
||||
thenStatement instanceof IASTCompoundStatement && !startsWithMacroExpansion(thenStatement)) {
|
||||
|
@ -3229,17 +3273,25 @@ public class CodeFormatterVisitor extends ASTVisitor implements ICPPASTVisitor,
|
|||
tailFormatter = new ClosingParensesisTailFormatter(
|
||||
preferences.insert_space_before_closing_paren_in_if, tailFormatter);
|
||||
scribe.setTailFormatter(tailFormatter);
|
||||
if (condExpr == null || condExpr instanceof IASTProblemExpression) {
|
||||
if (condition == null || condition instanceof IASTProblemHolder) {
|
||||
scribe.skipToToken(Token.tRPAREN);
|
||||
} else {
|
||||
condExpr.accept(this);
|
||||
condition.accept(this);
|
||||
}
|
||||
scribe.runTailFormatter();
|
||||
scribe.setTailFormatter(null);
|
||||
} else if (!(condition instanceof IASTProblemHolder)) {
|
||||
condition.accept(this);
|
||||
}
|
||||
} finally {
|
||||
fExpectSemicolonAfterDeclaration= true;
|
||||
}
|
||||
|
||||
boolean thenStatementIsBlock = false;
|
||||
if (thenStatement != null) {
|
||||
if (thenStatement instanceof IASTCompoundStatement && !startsWithMacroExpansion(thenStatement)) {
|
||||
if (condition != null && doNodeLocationsOverlap(condition, thenStatement)) {
|
||||
thenStatement.accept(this);
|
||||
} else if (thenStatement instanceof IASTCompoundStatement && !startsWithMacroExpansion(thenStatement)) {
|
||||
final IASTCompoundStatement block = (IASTCompoundStatement) thenStatement;
|
||||
thenStatementIsBlock = true;
|
||||
final List<IASTStatement> statements = Arrays.asList(block.getStatements());
|
||||
|
@ -3263,7 +3315,7 @@ public class CodeFormatterVisitor extends ASTVisitor implements ICPPASTVisitor,
|
|||
}
|
||||
}
|
||||
} else {
|
||||
if (node.getFileLocation().getNodeOffset() == thenStatement.getFileLocation().getNodeOffset()) {
|
||||
if (doNodesHaveSameOffset(node, thenStatement)) {
|
||||
startNode(thenStatement);
|
||||
}
|
||||
if (elseStatement == null && preferences.keep_simple_if_on_one_line) {
|
||||
|
@ -3310,6 +3362,9 @@ public class CodeFormatterVisitor extends ASTVisitor implements ICPPASTVisitor,
|
|||
}
|
||||
|
||||
if (elseStatement != null) {
|
||||
if (condition != null && doNodeLocationsOverlap(condition, elseStatement)) {
|
||||
elseStatement.accept(this);
|
||||
} else {
|
||||
if (peekNextToken() == Token.t_else) {
|
||||
if (thenStatementIsBlock) {
|
||||
scribe.printNextToken(Token.t_else, preferences.insert_space_after_closing_brace_in_block);
|
||||
|
@ -3340,6 +3395,7 @@ public class CodeFormatterVisitor extends ASTVisitor implements ICPPASTVisitor,
|
|||
scribe.unIndent();
|
||||
}
|
||||
}
|
||||
}
|
||||
return PROCESS_SKIP;
|
||||
}
|
||||
|
||||
|
@ -3944,6 +4000,11 @@ public class CodeFormatterVisitor extends ASTVisitor implements ICPPASTVisitor,
|
|||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the two given nodes have overlapping file locations. For nodes that are
|
||||
* normally separated by other tokens this is an indication that they were produced by the same
|
||||
* macro expansion.
|
||||
*/
|
||||
private static boolean doNodeLocationsOverlap(IASTNode node1, IASTNode node2) {
|
||||
IASTFileLocation loc1 = node1.getFileLocation();
|
||||
IASTFileLocation loc2 = node2.getFileLocation();
|
||||
|
@ -3951,6 +4012,15 @@ public class CodeFormatterVisitor extends ASTVisitor implements ICPPASTVisitor,
|
|||
loc1.getNodeOffset() < loc2.getNodeOffset() + loc2.getNodeLength();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the two given nodes have the same offset. For nodes that are normally
|
||||
* separated by other tokens this is an indication that they were produced by the same macro
|
||||
* expansion.
|
||||
*/
|
||||
private static boolean doNodesHaveSameOffset(IASTNode node1, IASTNode node2) {
|
||||
return node1.getFileLocation().getNodeOffset() == node2.getFileLocation().getNodeOffset();
|
||||
}
|
||||
|
||||
private void formatBlock(IASTCompoundStatement block, String block_brace_position,
|
||||
boolean insertSpaceBeforeOpeningBrace, boolean indentStatements) {
|
||||
formatBlockOpening(block, block_brace_position, insertSpaceBeforeOpeningBrace);
|
||||
|
|
|
@ -963,7 +963,7 @@ public class CodeFormatterTest extends BaseUITestCase {
|
|||
//M* A::c(M* tm) { N::iterator it = myN.find(tm); if (!it) return NULL; else return *it; }
|
||||
|
||||
//void A::a(C e) {
|
||||
// if (D::iterator it = m.find (e))
|
||||
// if (D::iterator it = m.find(e))
|
||||
// m.erase(it);
|
||||
//}
|
||||
//T* A::b(T* t) {
|
||||
|
@ -1505,6 +1505,24 @@ public class CodeFormatterTest extends BaseUITestCase {
|
|||
assertFormatterResult();
|
||||
}
|
||||
|
||||
//#define BLOCK { }
|
||||
//#define ALWAYS if(true)
|
||||
//
|
||||
//void foo() {
|
||||
//ALWAYS BLOCK
|
||||
//}
|
||||
|
||||
//#define BLOCK { }
|
||||
//#define ALWAYS if(true)
|
||||
//
|
||||
//void foo() {
|
||||
// ALWAYS
|
||||
// BLOCK
|
||||
//}
|
||||
public void testCompoundStatementAsMacro_Temp() throws Exception {
|
||||
assertFormatterResult();
|
||||
}
|
||||
|
||||
//#define BLOCK { }
|
||||
//#define DOIT1() { }
|
||||
//#define DOIT2() do { } while(false)
|
||||
|
@ -2400,6 +2418,37 @@ public class CodeFormatterTest extends BaseUITestCase {
|
|||
assertFormatterResult();
|
||||
}
|
||||
|
||||
//struct Stream {
|
||||
//Stream& operator <<(const char*);
|
||||
//};
|
||||
//Stream GetStream();
|
||||
//
|
||||
//#define MY_MACRO switch (0) case 0: default: if (bool x = false) ; else GetStream()
|
||||
//
|
||||
//void test() {
|
||||
//MY_MACRO << "Loooooooooooooooooooong string literal" << " another literal.";
|
||||
//MY_MACRO << "Looooooooooooooooooooong string literal" << " another literal.";
|
||||
//}
|
||||
|
||||
//struct Stream {
|
||||
// Stream& operator <<(const char*);
|
||||
//};
|
||||
//Stream GetStream();
|
||||
//
|
||||
//#define MY_MACRO switch (0) case 0: default: if (bool x = false) ; else GetStream()
|
||||
//
|
||||
//void test() {
|
||||
// MY_MACRO << "Loooooooooooooooooooong string literal" << " another literal.";
|
||||
// MY_MACRO << "Looooooooooooooooooooong string literal"
|
||||
// << " another literal.";
|
||||
//}
|
||||
public void testOverloadedLeftShiftChain_6() 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));
|
||||
assertFormatterResult();
|
||||
}
|
||||
|
||||
//int main() {
|
||||
// std::vector<std::vector<int>> test;
|
||||
// // some comment
|
||||
|
|
Loading…
Add table
Reference in a new issue