diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/formatter/CodeFormatterVisitor.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/formatter/CodeFormatterVisitor.java index e6d61b27016..79ca1369767 100644 --- a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/formatter/CodeFormatterVisitor.java +++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/formatter/CodeFormatterVisitor.java @@ -1313,12 +1313,12 @@ public class CodeFormatterVisitor extends ASTVisitor implements ICPPASTVisitor, scribe.space(); } Runnable tailFormatter = null; + IASTStatement bodyStmt= node.getBody(); if (DefaultCodeFormatterConstants.END_OF_LINE.equals(preferences.brace_position_for_method_declaration) && !hasMemberInitializers(node) && !(node instanceof ICPPASTFunctionWithTryBlock)) { - IASTStatement body = node.getBody(); - if (body instanceof IASTCompoundStatement && !startsWithMacroExpansion(body)) { + if (bodyStmt instanceof IASTCompoundStatement && !startsWithMacroExpansion(bodyStmt)) { tailFormatter = new TrailingTokenFormatter(Token.tLBRACE, - body.getFileLocation().getNodeOffset(), + bodyStmt.getFileLocation().getNodeOffset(), preferences.insert_space_before_opening_brace_in_method_declaration, false); scribe.setTailFormatter(tailFormatter); } @@ -1359,8 +1359,8 @@ public class CodeFormatterVisitor extends ASTVisitor implements ICPPASTVisitor, scribe.runTailFormatter(); scribe.setTailFormatter(null); } + // Body - IASTStatement bodyStmt= node.getBody(); if (bodyStmt instanceof IASTCompoundStatement) { if (startNode(bodyStmt)) { try { @@ -1833,21 +1833,13 @@ public class CodeFormatterVisitor extends ASTVisitor implements ICPPASTVisitor, if (withinMacroExpansion(node, scribe.scanner.getCurrentPosition())) { scribe.printNextToken(peekNextToken()); continueNode(node); - if (scribe.printComment()) scribe.space(); + if (scribe.printComment()) + scribe.space(); } - switch (node.getKey()) { - case IASTCompositeTypeSpecifier.k_struct: - scribe.printNextToken(Token.t_struct, false); - break; - case IASTCompositeTypeSpecifier.k_union: - scribe.printNextToken(Token.t_union, false); - break; - case ICPPASTCompositeTypeSpecifier.k_class: - scribe.printNextToken(Token.t_class, false); - break; - default: - assert false : "Unexpected composite type specifier"; //$NON-NLS-1$ + int token = peekNextToken(); + if (token == Token.t_struct || token == Token.t_class || token == Token.t_union) { + scribe.printNextToken(token, false); } final IASTName name= node.getName(); @@ -1867,8 +1859,8 @@ public class CodeFormatterVisitor extends ASTVisitor implements ICPPASTVisitor, scribe.space(); } } - } catch (UnsupportedOperationException exc) { - } catch (ExpansionOverlapsBoundaryException exc) { + } catch (UnsupportedOperationException e) { + } catch (ExpansionOverlapsBoundaryException e) { } final ListOptions options= new ListOptions(preferences.alignment_for_base_clause_in_type_declaration); options.fSpaceAfterSeparator= preferences.insert_space_after_comma_in_base_types; @@ -1886,8 +1878,12 @@ public class CodeFormatterVisitor extends ASTVisitor implements ICPPASTVisitor, if (preferences.indent_access_specifier_compare_to_type_header) { scribe.indent(); } - IASTDeclaration[] memberDecls= node.getMembers(); + if (scribe.scanner.getCurrentPosition() >= getNodeEndPosition(node)) { + return PROCESS_SKIP; + } scribe.startNewLine(); + + IASTDeclaration[] memberDecls= node.getMembers(); for (IASTDeclaration declaration : memberDecls) { if (preferences.indent_body_declarations_compare_to_access_specifier) { scribe.indent(); @@ -2149,24 +2145,36 @@ public class CodeFormatterVisitor extends ASTVisitor implements ICPPASTVisitor, } private int visit(ICPPASTCatchHandler node) { - if (preferences.insert_new_line_before_catch_in_try_statement) { - scribe.startNewLine(); + int token = peekNextToken(); + if (token == Token.t_catch) { + if (preferences.insert_new_line_before_catch_in_try_statement) { + scribe.startNewLine(); + } + scribe.printNextToken(token, true); } - scribe.printNextToken(Token.t_catch, true); - scribe.printNextToken(Token.tLPAREN, preferences.insert_space_before_opening_paren_in_catch); - if (preferences.insert_space_after_opening_paren_in_catch) { - scribe.space(); + token = peekNextToken(); + if (token == Token.tLPAREN) { + scribe.printNextToken(token, preferences.insert_space_before_opening_paren_in_catch); + if (preferences.insert_space_after_opening_paren_in_catch) { + scribe.space(); + } } final IASTDeclaration decl= node.getDeclaration(); if (decl != null) { formatInlineDeclaration(decl); } else if (node.isCatchAll()) { - scribe.printNextToken(Token.tELIPSE, false /* preferences.insert_space_before_ellipsis */); -// if (false /* preferences.insert_space_after_ellipsis */) { -// scribe.space(); -// } + token = peekNextToken(); + if (token == Token.tELIPSE) { + scribe.printNextToken(token, false /* preferences.insert_space_before_ellipsis */); +// if (false /* preferences.insert_space_after_ellipsis */) { +// scribe.space(); +// } + } + } + token = peekNextToken(); + if (token == Token.tRPAREN) { + scribe.printNextToken(token, preferences.insert_space_before_closing_paren_in_catch); } - scribe.printNextToken(Token.tRPAREN, preferences.insert_space_before_closing_paren_in_catch); final IASTStatement catchBody= node.getCatchBody(); if (catchBody != null) { catchBody.accept(this); @@ -2662,7 +2670,7 @@ public class CodeFormatterVisitor extends ASTVisitor implements ICPPASTVisitor, scribe.setTailFormatter(tailFormatter); } operand.accept(this); - scribe.restartAtOffset(getNodeEndLocation(operand)); + scribe.restartAtOffset(getNodeEndPosition(operand)); scribe.printTrailingComment(); } @@ -2898,9 +2906,10 @@ public class CodeFormatterVisitor extends ASTVisitor implements ICPPASTVisitor, try { scribe.alignFragment(alignment, 0); - final int operatorToken= node.isPointerDereference() ? Token.tARROW : Token.tDOT; scribe.printComment(); - scribe.printNextToken(operatorToken, false); + int token = peekNextToken(); + if (token == Token.tARROW || token == Token.tDOT) + scribe.printNextToken(token, false); scribe.printComment(); if (node instanceof ICPPASTFieldReference) { if (((ICPPASTFieldReference) node).isTemplate()) { @@ -3058,13 +3067,16 @@ public class CodeFormatterVisitor extends ASTVisitor implements ICPPASTVisitor, } private int visit(IASTDoStatement node) { - scribe.printNextToken(Token.t_do); + int token = peekNextToken(); + if (token == Token.t_do) { + scribe.printNextToken(token); + } final int line = scribe.line; final IASTStatement action = node.getBody(); formatAction(line, action, preferences.brace_position_for_block); - if (scribe.scanner.getCurrentPosition() < getNodeEndLocation(node)) { + if (scribe.scanner.getCurrentPosition() < getNodeEndPosition(node)) { if (peekNextToken() == Token.t_while) { if (preferences.insert_new_line_before_while_in_do_statement) { scribe.startNewLine(); @@ -3205,30 +3217,6 @@ public class CodeFormatterVisitor extends ASTVisitor implements ICPPASTVisitor, scribe.exitAlignment(alignment, true); if (body instanceof IASTCompoundStatement && !startsWithMacroExpansion(body)) { -// 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 { if (scribe.scanner.getCurrentPosition() <= body.getFileLocation().getNodeOffset()) { @@ -3549,15 +3537,11 @@ public class CodeFormatterVisitor extends ASTVisitor implements ICPPASTVisitor, private int visit(IASTSwitchStatement node) { final int headerIndent= scribe.numberOfIndentations; - /* - * 'switch' keyword - */ + // 'switch' keyword if (!startsWithMacroExpansion(node)) { scribe.printNextToken(Token.t_switch); } - /* - * Controller expression - */ + // Controller expression IASTExpression controllerExpression = node.getControllerExpression(); if (!doNodesHaveSameOffset(node, controllerExpression)) { scribe.printNextToken(Token.tLPAREN, preferences.insert_space_before_opening_paren_in_switch); @@ -3569,9 +3553,7 @@ public class CodeFormatterVisitor extends ASTVisitor implements ICPPASTVisitor, if (peekNextToken() == Token.tRPAREN) { scribe.printNextToken(Token.tRPAREN, preferences.insert_space_before_closing_paren_in_switch); } - /* - * switch body - */ + // switch body String brace_position = preferences.brace_position_for_switch; int braceIndent = -1; IASTStatement bodyStmt= node.getBody(); @@ -3989,9 +3971,8 @@ public class CodeFormatterVisitor extends ASTVisitor implements ICPPASTVisitor, private static boolean startsWithMacroExpansion(IASTNode node) { IASTNodeLocation[] locations= node.getNodeLocations(); - if (locations.length == 0) { - } else if (node instanceof IASTProblemHolder) { - } else if (locations[0] instanceof IASTMacroExpansionLocation) { + if (!(node instanceof IASTProblemHolder) && locations.length != 0 && + locations[0] instanceof IASTMacroExpansionLocation) { IASTFileLocation expansionLocation= locations[0].asFileLocation(); IASTFileLocation fileLocation= node.getFileLocation(); return expansionLocation.getNodeOffset() == fileLocation.getNodeOffset(); @@ -4001,9 +3982,8 @@ public class CodeFormatterVisitor extends ASTVisitor implements ICPPASTVisitor, private static boolean endsWithMacroExpansion(IASTNode node) { IASTNodeLocation[] locations= node.getNodeLocations(); - if (locations.length == 0) { - } else if (node instanceof IASTProblemHolder) { - } else if (locations[locations.length - 1] instanceof IASTMacroExpansionLocation) { + if (!(node instanceof IASTProblemHolder) && locations.length != 0 && + locations[locations.length - 1] instanceof IASTMacroExpansionLocation) { return true; } return false; @@ -4033,6 +4013,29 @@ public class CodeFormatterVisitor extends ASTVisitor implements ICPPASTVisitor, return true; } + /** + * Returns true if the given macro expansion is followed by a semicolon on the same + * line. + */ + private boolean looksLikeStatement(IASTMacroExpansionLocation location) { + IASTFileLocation fileLocation = location.asFileLocation(); + if (fileLocation == null) + return false; + int pos = fileLocation.getNodeOffset() + fileLocation.getNodeLength(); + localScanner.resetTo(pos, scribe.scannerEndPosition - 1); + Token token= localScanner.nextToken(); + if (token == null || token.getType() != Token.tSEMI) + return false; + // Check if the semicolon is on the same line. + localScanner.resetTo(pos, token.getOffset() - 1); + int c; + while ((c = localScanner.getNextChar()) != -1) { + if (c == '\n') + return false; + } + 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 @@ -4054,7 +4057,7 @@ public class CodeFormatterVisitor extends ASTVisitor implements ICPPASTVisitor, return node1.getFileLocation().getNodeOffset() == node2.getFileLocation().getNodeOffset(); } - private static int getNodeEndLocation(IASTNode node) { + private static int getNodeEndPosition(IASTNode node) { IASTFileLocation loc = node.getFileLocation(); return loc.getNodeOffset() + loc.getNodeLength(); } @@ -4067,40 +4070,43 @@ public class CodeFormatterVisitor extends ASTVisitor implements ICPPASTVisitor, private void formatBlockOpening(IASTCompoundStatement block, String block_brace_position, boolean insertSpaceBeforeOpeningBrace) { - if (!startsWithMacroExpansion(block)) { - if (scribe.scanner.getCurrentPosition() <= block.getFileLocation().getNodeOffset()) { - formatOpeningBrace(block_brace_position, insertSpaceBeforeOpeningBrace); + if (startsWithMacroExpansion(block)) { + if (!looksLikeStatement((IASTMacroExpansionLocation) block.getNodeLocations()[0])) { + scribe.startNewLine(); + scribe.printComment(); } - } else { - scribe.startNewLine(); - scribe.printComment(); + } else if (scribe.scanner.getCurrentPosition() <= block.getFileLocation().getNodeOffset()) { + formatOpeningBrace(block_brace_position, insertSpaceBeforeOpeningBrace); } } private void formatOpenedBlock(IASTCompoundStatement block, String block_brace_position, boolean indentStatements) { + final boolean startsWithStatementLikeMacro = startsWithMacroExpansion(block) && + looksLikeStatement((IASTMacroExpansionLocation) block.getNodeLocations()[0]); final boolean endsWithMacroExpansion= endsWithMacroExpansion(block); IASTStatement[] statements = block.getStatements(); final int statementsLength = statements.length; if (statementsLength != 0) { - scribe.startNewLine(); - if (indentStatements) { - scribe.indent(); + if (!startsWithStatementLikeMacro) { + scribe.startNewLine(); + if (indentStatements) + scribe.indent(); } formatStatements(Arrays.asList(statements), !endsWithMacroExpansion); } else { - if (preferences.insert_new_line_in_empty_block) { - scribe.startNewLine(); - } - if (indentStatements) { - scribe.indent(); + if (!startsWithStatementLikeMacro) { + if (preferences.insert_new_line_in_empty_block) + scribe.startNewLine(); + if (indentStatements) + scribe.indent(); } } scribe.printComment(); - if (indentStatements) { + if (indentStatements && !startsWithStatementLikeMacro) scribe.unIndent(); - } + if (!endsWithMacroExpansion) { formatClosingBrace(block_brace_position); } else if (!startsWithMacroExpansion(block)) { @@ -4131,12 +4137,18 @@ public class CodeFormatterVisitor extends ASTVisitor implements ICPPASTVisitor, scribe.startNewLine(); scribe.indent(); } - scribe.printNextToken(Token.tLBRACE, insertSpaceBeforeBrace); + int token = peekNextToken(); + if (token == Token.tLBRACE) { + scribe.printNextToken(token, insertSpaceBeforeBrace); + } scribe.printTrailingComment(); } private void formatClosingBrace(String brace_position) { - scribe.printNextToken(Token.tRBRACE); + int token = peekNextToken(); + if (token == Token.tRBRACE) { + scribe.printNextToken(token); + } scribe.printTrailingComment(); if (DefaultCodeFormatterConstants.NEXT_LINE_SHIFTED.equals(brace_position)) { scribe.unIndent(); @@ -4180,8 +4192,9 @@ public class CodeFormatterVisitor extends ASTVisitor implements ICPPASTVisitor, } } final IASTStatement statement= statements.get(statementsLength - 1); - final boolean statementIsNullStmt= statement instanceof IASTNullStatement; - if (!statementIsNullStmt) { + if (!(statement instanceof IASTNullStatement) && + (!startsWithMacroExpansion(statement) || + !looksLikeStatement((IASTMacroExpansionLocation) statement.getNodeLocations()[0]))) { scribe.startNewLine(); } statement.accept(this); diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/formatter/Scribe.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/formatter/Scribe.java index 3111375e8fc..714f94ae259 100644 --- a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/formatter/Scribe.java +++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/formatter/Scribe.java @@ -1599,7 +1599,7 @@ public class Scribe { } if (lastNumberOfNewLines >= 1) { // Ensure that the scribe is at the beginning of a new line - // only if no specific indentation has been previously set + // only if no specific indentation has been previously set. if (!preserveLineBreakIndentation) { column = 1; } @@ -2053,7 +2053,7 @@ public class Scribe { } boolean shouldSkip(int offset) { - return offset >= fSkipStartOffset; + return offset >= fSkipStartOffset && offset < fSkipEndOffset; } void skipRange(int offset, int endOffset) { diff --git a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/CodeFormatterTest.java b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/CodeFormatterTest.java index 789f4b18008..3d0fe5e5f4e 100644 --- a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/CodeFormatterTest.java +++ b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/CodeFormatterTest.java @@ -457,14 +457,14 @@ public class CodeFormatterTest extends BaseUITestCase { // //void break_indenter(int a, int b) { // break_start(); // This semicolon moves to its own line. - // if (a > b) { - // indentation_remains(); - // } + // if (a > b) { + // indentation_remains(); + // } // - // if (b > a) - // indentation_vanishes(); + // if (b > a) + // indentation_vanishes(); // - // break_end(); + // break_end(); // // if (b == a) // indentation_remains(); @@ -473,6 +473,41 @@ public class CodeFormatterTest extends BaseUITestCase { assertFormatterResult(); } + //struct SimpleStruct { + //int num; + //char name[]; + //float floatNum; + //}; + // + //#define SIZEOF(A, B) sizeof(A.B) + // + //const SimpleStruct array[] = { { SIZEOF(simpleStruct, num), + //#if FOO + //"foo" + //#else + //"bar" + //#endif + //, 0.5 }, { SIZEOF(simpleStruct, floatNum), "name", 1.1 } }; + + //struct SimpleStruct { + // int num; + // char name[]; + // float floatNum; + //}; + // + //#define SIZEOF(A, B) sizeof(A.B) + // + //const SimpleStruct array[] = { { SIZEOF(simpleStruct, num), + //#if FOO + // "foo" + //#else + // "bar" + //#endif + // , 0.5 }, { SIZEOF(simpleStruct, floatNum), "name", 1.1 } }; + public void testArrayInitializer() throws Exception { + assertFormatterResult(); + } + //int a=1+2; //int b= - a; //int c =b ++/-- b; @@ -2499,6 +2534,44 @@ public class CodeFormatterTest extends BaseUITestCase { assertFormatterResult(); } + //struct Stream { + //Stream& operator <<(const char*); + //}; + //Stream GetStream(); + // + //struct Voidifier { + //void operator&(Stream&); + //}; + // + //#define MY_MACRO(a) (a) ? (void) 0 : Voidifier() & GetStream() << " " + // + //void test() { + //MY_MACRO(false) + //<< "Loooooooooooooooooooooooooooooooooooooooong string literal"; + //} + + //struct Stream { + // Stream& operator <<(const char*); + //}; + //Stream GetStream(); + // + //struct Voidifier { + // void operator&(Stream&); + //}; + // + //#define MY_MACRO(a) (a) ? (void) 0 : Voidifier() & GetStream() << " " + // + //void test() { + // MY_MACRO(false) + // << "Loooooooooooooooooooooooooooooooooooooooong string literal"; + //} + public void testOverloadedLeftShiftChain_Bug373034() 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> test; // // some comment