1
0
Fork 0
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:
Sergey Prigogin 2011-09-14 12:22:17 -07:00
parent 1c153dcece
commit a090d9bd2c
2 changed files with 239 additions and 120 deletions

View file

@ -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);

View file

@ -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