1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-07-28 11:25:35 +02:00

Fix for 217435: Braces in macros confuse code formatter

This commit is contained in:
Anton Leherbauer 2008-02-15 12:24:49 +00:00
parent 7f2fe153bd
commit 2b53efe517
5 changed files with 594 additions and 441 deletions

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2006, 2007 Wind River Systems, Inc. and others.
* Copyright (c) 2006, 2008 Wind River Systems, Inc. and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@ -210,7 +210,7 @@ public class CodeFormatterVisitor extends CPPASTVisitor {
private MultiStatus fStatus;
public CodeFormatterVisitor(DefaultCodeFormatterOptions preferences, Map settings, int offset, int length) {
public CodeFormatterVisitor(DefaultCodeFormatterOptions preferences, Map<String, String> settings, int offset, int length) {
localScanner = new Scanner() {
public Token nextToken() {
Token t= super.nextToken();
@ -326,14 +326,9 @@ public class CodeFormatterVisitor extends CPPASTVisitor {
* @see org.eclipse.cdt.core.dom.ast.ASTVisitor#visit(org.eclipse.cdt.core.dom.ast.IASTDeclaration)
*/
public int visit(IASTDeclaration node) {
startNode(node);
int indentLevel= scribe.indentationLevel;
try {
IASTNodeLocation[] locations= node.getNodeLocations();
if (locations.length == 0) {
throw new AbortFormatting("Empty location array in " + node.getClass().getName()); //$NON-NLS-1$
} else if (locations[0] instanceof IASTMacroExpansion && !(node instanceof IASTProblemDeclaration)) {
skipNode(node);
} else
if (node instanceof IASTFunctionDefinition) {
return visit((IASTFunctionDefinition)node);
} else if (node instanceof IASTSimpleDeclaration) {
@ -375,6 +370,8 @@ public class CodeFormatterVisitor extends CPPASTVisitor {
scribe.unIndent();
}
}
} finally {
endOfNode(node);
}
return PROCESS_SKIP;
}
@ -383,12 +380,8 @@ public class CodeFormatterVisitor extends CPPASTVisitor {
* @see org.eclipse.cdt.core.dom.ast.ASTVisitor#visit(org.eclipse.cdt.core.dom.ast.IASTName)
*/
public int visit(IASTName node) {
IASTNodeLocation[] locations= node.getNodeLocations();
if (locations.length == 0) {
return PROCESS_SKIP;
} else if (locations[0] instanceof IASTMacroExpansion) {
formatNode(node);
} else
startNode(node);
try {
if (node instanceof ICPPASTQualifiedName) {
visit((ICPPASTQualifiedName)node);
} else if (node instanceof ICPPASTTemplateId) {
@ -396,6 +389,9 @@ public class CodeFormatterVisitor extends CPPASTVisitor {
} else {
formatNode(node);
}
} finally {
endOfNode(node);
}
return PROCESS_SKIP;
}
@ -403,14 +399,6 @@ public class CodeFormatterVisitor extends CPPASTVisitor {
* @see org.eclipse.cdt.core.dom.ast.ASTVisitor#visit(org.eclipse.cdt.core.dom.ast.IASTInitializer)
*/
public int visit(IASTInitializer node) {
// IASTNodeLocation[] locations= node.getNodeLocations();
// if (locations.length == 0) {
// return PROCESS_SKIP;
// } else if (locations[0] instanceof IASTMacroExpansion) {
// formatNode(node);
// return PROCESS_SKIP;
// }
if (node instanceof ICPPASTConstructorInitializer) {
visit((ICPPASTConstructorInitializer)node);
return PROCESS_SKIP;
@ -423,6 +411,8 @@ public class CodeFormatterVisitor extends CPPASTVisitor {
}
}
startNode(node);
try {
if (node instanceof IASTInitializerExpression) {
visit((IASTInitializerExpression)node);
} else if (node instanceof IASTInitializerList) {
@ -432,6 +422,9 @@ public class CodeFormatterVisitor extends CPPASTVisitor {
} else {
formatNode(node);
}
} finally {
endOfNode(node);
}
return PROCESS_SKIP;
}
@ -440,6 +433,7 @@ public class CodeFormatterVisitor extends CPPASTVisitor {
*/
public int visit(IASTParameterDeclaration parameterDeclaration) {
formatNode(parameterDeclaration);
endOfNode(parameterDeclaration);
return PROCESS_SKIP;
}
@ -447,14 +441,9 @@ public class CodeFormatterVisitor extends CPPASTVisitor {
* @see org.eclipse.cdt.core.dom.ast.ASTVisitor#visit(org.eclipse.cdt.core.dom.ast.IASTDeclarator)
*/
public int visit(IASTDeclarator node) {
IASTNodeLocation[] locations= node.getNodeLocations();
if (locations.length == 0) {
return PROCESS_SKIP;
} else if (locations[0] instanceof IASTMacroExpansion) {
formatNode(node);
return PROCESS_SKIP;
}
startNode(node);
try {
// common to all declarators
formatPointers(node.getPointerOperators());
if (scribe.printComment()) {
@ -489,6 +478,9 @@ public class CodeFormatterVisitor extends CPPASTVisitor {
if (initializer != null) {
initializer.accept(this);
}
} finally {
endOfNode(node);
}
return PROCESS_SKIP;
}
@ -496,12 +488,8 @@ public class CodeFormatterVisitor extends CPPASTVisitor {
* @see org.eclipse.cdt.core.dom.ast.ASTVisitor#visit(org.eclipse.cdt.core.dom.ast.IASTDeclSpecifier)
*/
public int visit(IASTDeclSpecifier node) {
IASTNodeLocation[] locations= node.getNodeLocations();
if (locations.length == 0) {
return PROCESS_SKIP;
} else if (locations[0] instanceof IASTMacroExpansion) {
formatNode(node);
} else
startNode(node);
try {
if (node instanceof ICPPASTCompositeTypeSpecifier) {
visit((ICPPASTCompositeTypeSpecifier)node);
} else if (node instanceof ICASTCompositeTypeSpecifier) {
@ -519,6 +507,9 @@ public class CodeFormatterVisitor extends CPPASTVisitor {
} else {
formatNode(node);
}
} finally {
endOfNode(node);
}
return PROCESS_SKIP;
}
@ -527,14 +518,8 @@ public class CodeFormatterVisitor extends CPPASTVisitor {
*/
public int visit(IASTExpression node) {
scribe.printComment();
IASTNodeLocation[] locations= node.getNodeLocations();
if (locations.length == 0) {
return PROCESS_SKIP;
} else if (locations[0] instanceof IASTMacroExpansion) {
skipNode(node);
} else if (locations[0].getNodeOffset()+locations[0].getNodeLength() < scribe.scanner.getCurrentPosition()) {
return PROCESS_SKIP;
} else
startNode(node);
try {
if (node instanceof IASTConditionalExpression) {
visit((IASTConditionalExpression)node);
} else if (node instanceof IASTFunctionCallExpression) {
@ -560,6 +545,9 @@ public class CodeFormatterVisitor extends CPPASTVisitor {
} else {
formatNode(node);
}
} finally {
endOfNode(node);
}
return PROCESS_SKIP;
}
@ -568,16 +556,9 @@ public class CodeFormatterVisitor extends CPPASTVisitor {
*/
public int visit(IASTStatement node) {
scribe.printComment();
startNode(node);
int indentLevel= scribe.indentationLevel;
IASTNodeLocation[] locations= node.getNodeLocations();
try {
if (locations.length == 0) {
return PROCESS_SKIP;
} else if (locations[0] instanceof IASTMacroExpansion && !(node instanceof IASTProblemStatement)) {
skipNode(node);
} else if (locations[0].getNodeOffset()+locations[0].getNodeLength() < scribe.scanner.getCurrentPosition()) {
return PROCESS_SKIP;
} else
if (node instanceof IASTCompoundStatement) {
visit((IASTCompoundStatement)node);
} else if (node instanceof IASTNullStatement) {
@ -632,6 +613,8 @@ public class CodeFormatterVisitor extends CPPASTVisitor {
scribe.unIndent();
}
}
} finally {
endOfNode(node);
}
return PROCESS_SKIP;
}
@ -639,18 +622,23 @@ public class CodeFormatterVisitor extends CPPASTVisitor {
/*
* @see org.eclipse.cdt.core.dom.ast.ASTVisitor#visit(org.eclipse.cdt.core.dom.ast.IASTTypeId)
*/
public int visit(IASTTypeId typeId) {
if (typeId instanceof IASTProblemHolder) {
throw new ASTProblemException(((IASTProblemHolder)typeId).getProblem());
public int visit(IASTTypeId node) {
startNode(node);
try {
if (node instanceof IASTProblemHolder) {
throw new ASTProblemException(((IASTProblemHolder)node).getProblem());
}
IASTDeclSpecifier declSpec= typeId.getDeclSpecifier();
IASTDeclSpecifier declSpec= node.getDeclSpecifier();
if (declSpec != null) {
declSpec.accept(this);
}
IASTDeclarator declarator= typeId.getAbstractDeclarator();
IASTDeclarator declarator= node.getAbstractDeclarator();
if (declarator != null) {
declarator.accept(this);
}
} finally {
endOfNode(node);
}
return PROCESS_SKIP;
}
@ -659,6 +647,7 @@ public class CodeFormatterVisitor extends CPPASTVisitor {
*/
public int visit(IASTEnumerator enumerator) {
formatNode(enumerator);
endOfNode(enumerator);
return PROCESS_SKIP;
}
@ -675,6 +664,7 @@ public class CodeFormatterVisitor extends CPPASTVisitor {
*/
public int visit(ICPPASTBaseSpecifier specifier) {
formatNode(specifier);
endOfNode(specifier);
return PROCESS_SKIP;
}
@ -683,6 +673,8 @@ public class CodeFormatterVisitor extends CPPASTVisitor {
*/
public int visit(ICPPASTNamespaceDefinition node) {
scribe.printComment();
startNode(node);
try {
final int line= scribe.line;
// namespace <name>
scribe.printNextToken(Token.t_namespace, false);
@ -710,6 +702,9 @@ public class CodeFormatterVisitor extends CPPASTVisitor {
scribe.unIndent();
}
formatClosingBrace(preferences.brace_position_for_namespace_declaration);
} finally {
endOfNode(node);
}
return PROCESS_SKIP;
}
@ -750,13 +745,8 @@ public class CodeFormatterVisitor extends CPPASTVisitor {
* @see org.eclipse.cdt.core.dom.ast.cpp.CPPASTVisitor#visit(org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateParameter)
*/
public int visit(ICPPASTTemplateParameter node) {
startNode(node);
try {
IASTNodeLocation[] locations= node.getNodeLocations();
if (locations.length == 0) {
return PROCESS_SKIP;
} else if (locations[0] instanceof IASTMacroExpansion) {
skipNode(node);
} else
if (node instanceof ICPPASTSimpleTypeTemplateParameter) {
visit((ICPPASTSimpleTypeTemplateParameter)node);
} else if (node instanceof ICPPASTTemplatedTypeTemplateParameter) {
@ -766,11 +756,13 @@ public class CodeFormatterVisitor extends CPPASTVisitor {
}
} catch (ASTProblemException e) {
skipNode(node);
} finally {
endOfNode(node);
}
return PROCESS_SKIP;
}
public int visit(ICPPASTSimpleTypeTemplateParameter node) {
private int visit(ICPPASTSimpleTypeTemplateParameter node) {
switch (node.getParameterType()) {
case ICPPASTSimpleTypeTemplateParameter.st_class:
scribe.printNextToken(Token.t_class);
@ -794,7 +786,7 @@ public class CodeFormatterVisitor extends CPPASTVisitor {
return PROCESS_SKIP;
}
public int visit(ICPPASTTemplatedTypeTemplateParameter node) {
private int visit(ICPPASTTemplatedTypeTemplateParameter node) {
scribe.printNextToken(Token.t_template, scribe.printComment());
scribe.printNextToken(Token.tLT, scribe.printComment());
if (scribe.printComment()) {
@ -822,12 +814,17 @@ public class CodeFormatterVisitor extends CPPASTVisitor {
}
private int visit(ICPPASTConstructorInitializer node) {
startNode(node);
try {
scribe.printNextToken(Token.tLPAREN, false);
final IASTExpression value= node.getExpression();
if (value != null) {
value.accept(this);
}
scribe.printNextToken(Token.tRPAREN, false);
} finally {
endOfNode(node);
}
return PROCESS_SKIP;
}
@ -860,11 +857,16 @@ public class CodeFormatterVisitor extends CPPASTVisitor {
decl.accept(this);
IASTStatement bodyStmt= node.getBody();
if (bodyStmt instanceof IASTCompoundStatement) {
startNode(bodyStmt);
try {
formatLeftCurlyBrace(line, preferences.brace_position_for_method_declaration);
formatBlock((IASTCompoundStatement) bodyStmt,
preferences.brace_position_for_method_declaration,
preferences.insert_space_before_opening_brace_in_method_declaration,
preferences.indent_statements_compare_to_body);
} finally {
endOfNode(bodyStmt);
}
} else {
bodyStmt.accept(this);
}
@ -977,7 +979,7 @@ public class CodeFormatterVisitor extends CPPASTVisitor {
}
private int visit(IASTStandardFunctionDeclarator node) {
final List parameters = Arrays.asList(node.getParameters());
final List<IASTParameterDeclaration> parameters = Arrays.asList(node.getParameters());
final ListAlignment align= new ListAlignment(preferences.alignment_for_parameters_in_method_declaration);
align.fSpaceBeforeOpeningParen= preferences.insert_space_before_opening_paren_in_method_declaration;
align.fSpaceAfterOpeningParen= preferences.insert_space_after_opening_paren_in_method_declaration;
@ -1014,7 +1016,7 @@ public class CodeFormatterVisitor extends CPPASTVisitor {
}
private int visit(ICASTKnRFunctionDeclarator node) {
final List parameters= Arrays.asList(node.getParameterNames());
final List<IASTName> parameters= Arrays.asList(node.getParameterNames());
ListAlignment align= new ListAlignment(preferences.alignment_for_parameters_in_method_declaration);
align.fSpaceAfterOpeningParen= preferences.insert_space_after_opening_paren_in_method_declaration;
align.fSpaceBeforeClosingParen= preferences.insert_space_before_closing_paren_in_method_declaration;
@ -1065,8 +1067,8 @@ public class CodeFormatterVisitor extends CPPASTVisitor {
private int visit(IASTSimpleDeclaration node) {
IASTDeclSpecifier declSpec= node.getDeclSpecifier();
declSpec.accept(this);
final List declarators= Arrays.asList(node.getDeclarators());
if (declarators.size() > 0) {
final List<IASTDeclarator> declarators= Arrays.asList(node.getDeclarators());
if (declarators.size() >= 1) {
if (scribe.printComment() || peekNextToken() == Token.tIDENTIFIER) {
scribe.space();
}
@ -1196,7 +1198,7 @@ public class CodeFormatterVisitor extends CPPASTVisitor {
node.getName().accept(this);
// base specifiers
final List baseSpecifiers= Arrays.asList(node.getBaseSpecifiers());
final List<ICPPASTBaseSpecifier> baseSpecifiers= Arrays.asList(node.getBaseSpecifiers());
if (baseSpecifiers.size() > 0) {
scribe.printNextToken(Token.tCOLON, true /*preferences.insert_space_before_colon_in_composite_type_specifier*/);
scribe.space();
@ -1301,7 +1303,7 @@ public class CodeFormatterVisitor extends CPPASTVisitor {
* @param encloseInParen
* @param addEllipsis
*/
private void formatList(List elements, ListAlignment align, boolean encloseInParen, boolean addEllipsis) {
private void formatList(List<? extends IASTNode> elements, ListAlignment align, boolean encloseInParen, boolean addEllipsis) {
if (encloseInParen)
scribe.printNextToken(Token.tLPAREN, align.fSpaceBeforeOpeningParen);
@ -1349,7 +1351,7 @@ public class CodeFormatterVisitor extends CPPASTVisitor {
if (i > 0 && align.fSpaceAfterComma) {
scribe.space();
}
final IASTNode node= (IASTNode) elements.get(i);
final IASTNode node= elements.get(i);
if (node instanceof ICPPASTConstructorChainInitializer) {
// this is a special case
visit((ICPPASTConstructorChainInitializer)node);
@ -1497,7 +1499,7 @@ public class CodeFormatterVisitor extends CPPASTVisitor {
}
private int visit(IASTExpressionList node) {
final List expressions = Arrays.asList(node.getExpressions());
final List<IASTExpression> expressions = Arrays.asList(node.getExpressions());
final ListAlignment align= new ListAlignment(preferences.alignment_for_arguments_in_method_invocation);
align.fSpaceAfterOpeningParen= preferences.insert_space_after_opening_paren_in_method_invocation;
align.fSpaceBeforeClosingParen= preferences.insert_space_before_closing_paren_in_method_invocation;
@ -1569,8 +1571,13 @@ public class CodeFormatterVisitor extends CPPASTVisitor {
}
private int visit(IASTInitializerExpression node) {
Alignment expressionAlignment =scribe.createAlignment(
"assignmentExpression", //$NON-NLS-1$
if (node.getPropertyInParent() == IASTInitializerList.NESTED_INITIALIZER) {
// nested initializer expression, no need to apply extra alignment
node.getExpression().accept(this);
} else {
// declaration initializer
Alignment expressionAlignment= scribe.createAlignment(
"declarationInitializer", //$NON-NLS-1$
// need configurable alignment
Alignment.M_COMPACT_SPLIT,
1,
@ -1591,13 +1598,14 @@ public class CodeFormatterVisitor extends CPPASTVisitor {
}
} while (!ok);
scribe.exitAlignment(expressionAlignment, true);
}
return PROCESS_SKIP;
}
private int visit(IASTInitializerList node) {
scribe.printComment();
final List initializers = Arrays.asList(node.getInitializers());
final List<IASTInitializer> initializers = Arrays.asList(node.getInitializers());
if (initializers.isEmpty() && preferences.keep_empty_array_initializer_on_one_line) {
scribe.printNextToken(Token.tLBRACE, preferences.insert_space_before_opening_brace_in_array_initializer);
scribe.printNextToken(Token.tRBRACE, preferences.insert_space_between_empty_braces_in_array_initializer);
@ -1619,6 +1627,14 @@ public class CodeFormatterVisitor extends CPPASTVisitor {
align.fContinuationIndentation= preferences.continuation_indentation_for_array_initializer;
formatList(initializers, align, false, false);
// handle trailing comma
if (peekNextToken() == Token.tCOMMA) {
scribe.printNextToken(Token.tCOMMA, align.fSpaceBeforeComma);
if (align.fSpaceAfterComma) {
scribe.space();
}
}
if (preferences.insert_new_line_before_closing_brace_in_array_initializer) {
scribe.startNewLine();
}
@ -1798,23 +1814,9 @@ public class CodeFormatterVisitor extends CPPASTVisitor {
final int line = scribe.line;
final IASTStatement action = node.getBody();
if (action != null) {
if (action instanceof IASTCompoundStatement) {
formatLeftCurlyBrace(line, preferences.brace_position_for_block);
visit((IASTCompoundStatement)action);
} else if (action instanceof IASTNullStatement) {
scribe.indent();
visit((IASTNullStatement)this);
scribe.unIndent();
} else {
scribe.startNewLine();
scribe.indent();
action.accept(this);
scribe.unIndent();
scribe.startNewLine();
}
}
formatAction(line, action, preferences.brace_position_for_block);
if (peekNextToken() == Token.t_while) {
if (preferences.insert_new_line_before_while_in_do_statement) {
scribe.startNewLine();
}
@ -1828,6 +1830,7 @@ public class CodeFormatterVisitor extends CPPASTVisitor {
node.getCondition().accept(this);
scribe.printNextToken(Token.tRPAREN, preferences.insert_space_before_closing_paren_in_while);
}
scribe.printNextToken(Token.tSEMI, preferences.insert_space_before_semicolon);
scribe.printTrailingComment();
return PROCESS_SKIP;
@ -1898,7 +1901,7 @@ public class CodeFormatterVisitor extends CPPASTVisitor {
}
scribe.printNextToken(Token.tRPAREN, preferences.insert_space_before_closing_paren_in_for);
formatAction(line, node.getBody(), preferences.brace_position_for_block, preferences.insert_space_before_opening_brace_in_block);
formatAction(line, node.getBody(), preferences.brace_position_for_block);
return PROCESS_SKIP;
}
@ -1925,7 +1928,7 @@ public class CodeFormatterVisitor extends CPPASTVisitor {
if (thenStatement instanceof IASTCompoundStatement) {
final IASTCompoundStatement block = (IASTCompoundStatement) thenStatement;
thenStatementIsBlock = true;
final List statements = Arrays.asList(block.getStatements());
final List<IASTStatement> statements = Arrays.asList(block.getStatements());
if (isGuardClause(block, statements) && elseStatement == null && preferences.keep_guardian_clause_on_one_line) {
/*
* Need a specific formatting for guard clauses
@ -1934,7 +1937,7 @@ public class CodeFormatterVisitor extends CPPASTVisitor {
*/
scribe.printNextToken(Token.tLBRACE, preferences.insert_space_before_opening_brace_in_block);
scribe.space();
((IASTStatement) statements.get(0)).accept(this);
statements.get(0).accept(this);
scribe.printNextToken(Token.tRBRACE, true);
scribe.printTrailingComment();
} else {
@ -2115,18 +2118,20 @@ public class CodeFormatterVisitor extends CPPASTVisitor {
scribe.indent();
}
IASTStatement bodyStmt= node.getBody();
final List statements;
final List<IASTStatement> statements;
if (bodyStmt instanceof IASTCompoundStatement) {
statements= Arrays.asList(((IASTCompoundStatement)bodyStmt).getStatements());
} else {
statements= Collections.singletonList(bodyStmt);
}
final int statementsLength = statements.size();
if (statementsLength != 0) {
startNode(bodyStmt);
try {
boolean wasACase = false;
boolean wasAStatement = false;
if (statementsLength != 0) {
for (int i = 0; i < statementsLength; i++) {
final IASTStatement statement = (IASTStatement) statements.get(i);
final IASTStatement statement = statements.get(i);
if (statement instanceof IASTCaseStatement || statement instanceof IASTDefaultStatement) {
if (wasACase) {
scribe.startNewLine();
@ -2172,14 +2177,17 @@ public class CodeFormatterVisitor extends CPPASTVisitor {
}
bracePosition = preferences.brace_position_for_block_in_case;
try {
startNode(statement);
formatBlock((IASTCompoundStatement) statement, bracePosition,
preferences.insert_space_after_colon_in_case,
preferences.indent_statements_compare_to_block);
} catch (ASTProblemException e) {
if (i < statementsLength - 1) {
final IASTStatement nextStatement = (IASTStatement) statements.get(i + 1);
final IASTStatement nextStatement = statements.get(i + 1);
skipToNode(nextStatement);
}
} finally {
endOfNode(statement);
}
if (preferences.indent_switchstatements_compare_to_cases) {
scribe.indent();
@ -2187,14 +2195,17 @@ public class CodeFormatterVisitor extends CPPASTVisitor {
} else {
bracePosition = preferences.brace_position_for_block;
try {
startNode(statement);
formatBlock((IASTCompoundStatement) statement, bracePosition,
preferences.insert_space_before_opening_brace_in_block,
preferences.indent_statements_compare_to_block);
} catch (ASTProblemException e) {
if (i < statementsLength - 1) {
final IASTStatement nextStatement = (IASTStatement) statements.get(i + 1);
final IASTStatement nextStatement = statements.get(i + 1);
skipToNode(nextStatement);
}
} finally {
endOfNode(statement);
}
}
wasAStatement = true;
@ -2205,7 +2216,7 @@ public class CodeFormatterVisitor extends CPPASTVisitor {
statement.accept(this);
} catch (ASTProblemException e) {
if (i < statementsLength - 1) {
final IASTStatement nextStatement = (IASTStatement) statements.get(i + 1);
final IASTStatement nextStatement = statements.get(i + 1);
skipToNode(nextStatement);
}
}
@ -2217,11 +2228,14 @@ public class CodeFormatterVisitor extends CPPASTVisitor {
}
scribe.printComment();
}
}
if ((wasACase || wasAStatement) && preferences.indent_switchstatements_compare_to_cases) {
scribe.unIndent();
}
} finally {
endOfNode(bodyStmt);
}
}
if (preferences.indent_switchstatements_compare_to_switch) {
scribe.unIndent();
}
@ -2246,7 +2260,7 @@ public class CodeFormatterVisitor extends CPPASTVisitor {
scribe.printNextToken(Token.tRPAREN, preferences.insert_space_before_closing_paren_in_while);
formatAction(line, node.getBody(), preferences.brace_position_for_block, preferences.insert_space_before_opening_brace_in_block);
formatAction(line, node.getBody(), preferences.brace_position_for_block);
return PROCESS_SKIP;
}
@ -2263,32 +2277,8 @@ public class CodeFormatterVisitor extends CPPASTVisitor {
}
private void formatNode(IASTNode node) {
final IASTNodeLocation[] locations= node.getNodeLocations();
final IASTNodeLocation minLocation= getMinFileLocation(locations);
if (minLocation != null) {
final IASTNodeLocation maxLocation= getMaxFileLocation(locations);
if (maxLocation != null) {
final int startOffset= minLocation.getNodeOffset();
final int endOffset= maxLocation.getNodeOffset() + maxLocation.getNodeLength();
scribe.printRaw(startOffset, endOffset - startOffset);
}
}
}
private static IASTFileLocation getMaxFileLocation(IASTNodeLocation[] locations) {
if (locations == null || locations.length == 0) {
return null;
}
final IASTNodeLocation nodeLocation= locations[locations.length-1];
return nodeLocation.asFileLocation();
}
private static IASTFileLocation getMinFileLocation(IASTNodeLocation[] locations) {
if (locations == null || locations.length == 0) {
return null;
}
final IASTNodeLocation nodeLocation= locations[0];
return nodeLocation.asFileLocation();
scribe.printComment();
skipNode(node);
}
private void exitAlignments() {
@ -2297,11 +2287,60 @@ public class CodeFormatterVisitor extends CPPASTVisitor {
}
}
/**
* Test whether the next node location is inside a macro expansion. If it is
* a macro expansion, formatting will be skipped until the next node outside
* the expansion is reached.
*
* @param node the AST node to be tested
*/
private void startNode(IASTNode node) {
IASTNodeLocation[] locations= node.getNodeLocations();
if (locations.length == 0) {
} else if (node instanceof IASTProblemHolder) {
} else if (locations[0] instanceof IASTMacroExpansion) {
IASTFileLocation expansionLocation= locations[0].asFileLocation();
int startOffset= expansionLocation.getNodeOffset();
scribe.skipRange(startOffset, startOffset + expansionLocation.getNodeLength());
} else {
IASTFileLocation fileLocation= node.getFileLocation();
scribe.resetToOffset(fileLocation.getNodeOffset());
}
}
private void endOfNode(IASTNode node) {
IASTNodeLocation[] locations= node.getNodeLocations();
if (locations.length == 0) {
} else if (node instanceof IASTProblemHolder) {
} else if (locations[0] instanceof IASTMacroExpansion) {
IASTFileLocation expansionLocation= locations[0].asFileLocation();
int macroEndOffset= expansionLocation.getNodeOffset() + expansionLocation.getNodeLength();
IASTFileLocation fileLocation= node.getFileLocation();
int nodeEndOffset= fileLocation.getNodeOffset() + fileLocation.getNodeLength();
if (nodeEndOffset >= macroEndOffset) {
IASTNode parent= node.getParent();
IASTFileLocation parentLocation= parent.getFileLocation();
int parentEndOffset= parentLocation.getNodeOffset() + parentLocation.getNodeLength();
if (parentEndOffset > nodeEndOffset) {
scribe.resetToOffset(nodeEndOffset);
} else if (parentEndOffset == nodeEndOffset) {
if (node instanceof IASTCompoundStatement
&& !(parent instanceof IASTCompoundStatement || parent instanceof IASTDoStatement)) {
scribe.resetToOffset(nodeEndOffset);
}
}
}
} else {
IASTFileLocation fileLocation= node.getFileLocation();
int nodeEndOffset= fileLocation.getNodeOffset() + fileLocation.getNodeLength();
scribe.resetToOffset(nodeEndOffset);
}
}
private void skipNode(IASTNode node) {
final IASTNodeLocation[] locations= node.getNodeLocations();
final IASTNodeLocation maxLocation= getMaxFileLocation(locations);
if (maxLocation != null) {
final int endOffset= maxLocation.getNodeOffset() + maxLocation.getNodeLength();
final IASTNodeLocation fileLocation= node.getFileLocation();
if (fileLocation != null) {
final int endOffset= fileLocation.getNodeOffset() + fileLocation.getNodeLength();
final int currentOffset= scribe.scanner.getCurrentTokenEndPosition() + 1;
final int restLength= endOffset - currentOffset;
if (restLength > 0) {
@ -2311,10 +2350,9 @@ public class CodeFormatterVisitor extends CPPASTVisitor {
}
private void skipToNode(IASTNode node) {
final IASTNodeLocation[] locations= node.getNodeLocations();
final IASTNodeLocation minLocation= getMinFileLocation(locations);
if (minLocation != null) {
final int startOffset= minLocation.getNodeOffset();
final IASTNodeLocation fileLocation= node.getFileLocation();
if (fileLocation != null) {
final int startOffset= fileLocation.getNodeOffset();
final int currentOffset= scribe.scanner.getCurrentTokenEndPosition() + 1;
final int restLength= startOffset - currentOffset;
if (restLength > 0) {
@ -2323,38 +2361,45 @@ public class CodeFormatterVisitor extends CPPASTVisitor {
}
}
private void formatAction(final int line, final IASTStatement stmt, String brace_position, boolean insertLineForSingleStatement) {
private void formatAction(final int line, final IASTStatement stmt, String brace_position) {
if (stmt != null) {
if (stmt instanceof IASTCompoundStatement) {
if (stmt instanceof IASTCompoundStatement && !startsWithMacroExpansion(stmt)) {
formatLeftCurlyBrace(line, brace_position);
startNode(stmt);
try {
formatBlock((IASTCompoundStatement)stmt, brace_position, preferences.insert_space_before_opening_brace_in_block, preferences.indent_statements_compare_to_block);
} finally {
endOfNode(stmt);
}
} else if (stmt instanceof IASTNullStatement) {
scribe.indent();
if (preferences.put_empty_statement_on_new_line) {
scribe.startNewLine();
}
visit((IASTNullStatement)stmt);
stmt.accept(this);
scribe.unIndent();
} else {
scribe.startNewLine();
scribe.indent();
stmt.accept(this);
scribe.unIndent();
if (insertLineForSingleStatement) {
scribe.startNewLine();
}
}
}
}
private void formatBlock(IASTCompoundStatement block, String block_brace_position, boolean insertSpaceBeforeOpeningBrace, boolean indentStatements) {
IASTNodeLocation[] locations= block.getNodeLocations();
private boolean startsWithMacroExpansion(IASTNode node) {
IASTNodeLocation[] locations= node.getNodeLocations();
if (locations.length == 0) {
return;
} else if (node instanceof IASTProblemHolder) {
} else if (locations[0] instanceof IASTMacroExpansion) {
formatNode(block);
return;
IASTFileLocation expansionLocation= locations[0].asFileLocation();
IASTFileLocation fileLocation= node.getFileLocation();
return expansionLocation.getNodeOffset() == fileLocation.getNodeOffset();
}
return false;
}
private void formatBlock(IASTCompoundStatement block, String block_brace_position, boolean insertSpaceBeforeOpeningBrace, boolean indentStatements) {
formatOpeningBrace(block_brace_position, insertSpaceBeforeOpeningBrace);
IASTStatement[] statements = block.getStatements();
final int statementsLength = statements.length;
@ -2415,18 +2460,18 @@ public class CodeFormatterVisitor extends CPPASTVisitor {
}
}
private void formatStatements(final List statements, boolean insertNewLineAfterLastStatement) {
private void formatStatements(final List<IASTStatement> statements, boolean insertNewLineAfterLastStatement) {
final int statementsLength = statements.size();
if (statementsLength > 1) {
IASTStatement previousStatement = (IASTStatement) statements.get(0);
IASTStatement previousStatement = statements.get(0);
try {
previousStatement.accept(this);
} catch (ASTProblemException e) {
skipToNode((IASTStatement) statements.get(1));
skipToNode(statements.get(1));
}
final boolean previousStatementIsNullStmt = previousStatement instanceof IASTNullStatement;
for (int i = 1; i < statementsLength - 1; i++) {
final IASTStatement statement = (IASTStatement) statements.get(i);
final IASTStatement statement = statements.get(i);
final boolean statementIsNullStmt = statement instanceof IASTNullStatement;
if ((previousStatementIsNullStmt && !statementIsNullStmt)
|| (!previousStatementIsNullStmt && !statementIsNullStmt)) {
@ -2435,11 +2480,11 @@ public class CodeFormatterVisitor extends CPPASTVisitor {
try {
statement.accept(this);
} catch (ASTProblemException e) {
skipToNode((IASTStatement) statements.get(i + 1));
skipToNode(statements.get(i + 1));
}
previousStatement = statement;
}
final IASTStatement statement = ((IASTStatement) statements.get(statementsLength - 1));
final IASTStatement statement = statements.get(statementsLength - 1);
final boolean statementIsNullStmt = statement instanceof IASTNullStatement;
if ((previousStatementIsNullStmt && !statementIsNullStmt)
|| (!previousStatementIsNullStmt && !statementIsNullStmt)) {
@ -2447,7 +2492,7 @@ public class CodeFormatterVisitor extends CPPASTVisitor {
}
statement.accept(this);
} else {
final IASTStatement statement = (IASTStatement) statements.get(0);
final IASTStatement statement = statements.get(0);
statement.accept(this);
}
if (insertNewLineAfterLastStatement) {
@ -2483,6 +2528,9 @@ public class CodeFormatterVisitor extends CPPASTVisitor {
}
protected int peekNextToken() {
if (scribe.shouldSkip(scribe.scanner.getCurrentPosition())) {
return Token.tBADCHAR;
}
localScanner.resetTo(scribe.scanner.getCurrentPosition(), scribe.scannerEndPosition - 1);
int token = localScanner.getNextToken();
loop: while(true) {
@ -2498,28 +2546,7 @@ public class CodeFormatterVisitor extends CPPASTVisitor {
return token;
}
protected boolean isClosingTemplateToken() {
localScanner.resetTo(scribe.scanner.getCurrentPosition(), scribe.scannerEndPosition - 1);
int token = localScanner.getNextToken();
loop: while(true) {
switch(token) {
case Token.tBLOCKCOMMENT :
case Token.tLINECOMMENT :
token = localScanner.getNextToken();
continue loop;
default:
break loop;
}
}
switch(token) {
case Token.tGT :
case Token.tSHIFTR :
return true;
}
return false;
}
private boolean isGuardClause(IASTCompoundStatement block, List statements) {
private boolean isGuardClause(IASTCompoundStatement block, List<IASTStatement> statements) {
IASTNodeLocation[] locations= block.getNodeLocations();
if (locations.length == 0) {
return false;
@ -2548,24 +2575,24 @@ public class CodeFormatterVisitor extends CPPASTVisitor {
* @param translationUnit the {@link IASTTranslationUnit}, may be <code>null</code>
* @return a {@link List} of {@link Position}s
*/
private static List collectInactiveCodePositions(IASTTranslationUnit translationUnit) {
private static List<Position> collectInactiveCodePositions(IASTTranslationUnit translationUnit) {
if (translationUnit == null) {
return Collections.EMPTY_LIST;
return Collections.emptyList();
}
String fileName = translationUnit.getFilePath();
if (fileName == null) {
return Collections.EMPTY_LIST;
return Collections.emptyList();
}
List positions = new ArrayList();
List<Position> positions = new ArrayList<Position>();
int inactiveCodeStart = -1;
boolean inInactiveCode = false;
Stack inactiveCodeStack = new Stack();
Stack<Boolean> inactiveCodeStack = new Stack<Boolean>();
IASTPreprocessorStatement[] preprocStmts = translationUnit.getAllPreprocessorStatements();
for (int i = 0; i < preprocStmts.length; i++) {
IASTPreprocessorStatement statement = preprocStmts[i];
if (!fileName.equals(statement.getContainingFilename())) {
if (!statement.isPartOfTranslationUnitFile()) {
// preprocessor directive is from a different file
continue;
}
@ -2622,7 +2649,7 @@ public class CodeFormatterVisitor extends CPPASTVisitor {
}
} else if (statement instanceof IASTPreprocessorEndifStatement) {
try {
boolean wasInInactiveCode = ((Boolean)inactiveCodeStack.pop()).booleanValue();
boolean wasInInactiveCode = inactiveCodeStack.pop().booleanValue();
if (inInactiveCode && !wasInInactiveCode) {
int inactiveCodeEnd = nodeLocation.getNodeOffset();
positions.add(new Position(inactiveCodeStart, inactiveCodeEnd - inactiveCodeStart));

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2000, 2007 IBM Corporation and others.
* Copyright (c) 2000, 2008 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@ -92,10 +92,14 @@ public class Scribe {
private boolean preserveNewlines;
private List fSkipPositions= Collections.EMPTY_LIST;
private List<Position> fSkipPositions= Collections.emptyList();
private boolean skipOverInactive;
private int fSkipTokensFrom= Integer.MAX_VALUE;
private int fSkipTokensTo;
private int fSkippedIndentations;
Scribe(CodeFormatterVisitor formatter, int offset, int length) {
scanner= new Scanner();
this.formatter= formatter;
@ -532,6 +536,10 @@ public class Scribe {
}
public void indent() {
if (shouldSkip(scanner.getCurrentPosition())) {
fSkippedIndentations++;
return;
}
indentationLevel+= indentationSize;
numberOfIndentations++;
}
@ -549,7 +557,7 @@ public class Scribe {
/**
* @param list
*/
public void setSkipPositions(List list) {
public void setSkipPositions(List<Position> list) {
fSkipPositions= list;
skipOverInactive= !list.isEmpty();
}
@ -611,6 +619,9 @@ public class Scribe {
if (length <= 0) {
return;
}
if (shouldSkip(scanner.getCurrentPosition())) {
return;
}
if (startOffset > scanner.getCurrentPosition()) {
printComment();
}
@ -649,20 +660,26 @@ public class Scribe {
needSpace= false;
}
switch (currentToken.type) {
case Token.tLBRACE:
case Token.tLBRACE: {
// int currentPosition= scanner.getCurrentPosition();
scanner.resetTo(scanner.getCurrentTokenStartPosition(), scannerEndPosition-1);
formatOpeningBrace(formatter.preferences.brace_position_for_block, formatter.preferences.insert_space_before_opening_brace_in_block);
if (formatter.preferences.indent_statements_compare_to_block) {
indent();
}
// scanner.resetTo(currentPosition, scannerEndPosition-1);
break;
case Token.tRBRACE:
}
case Token.tRBRACE: {
// int currentPosition= scanner.getCurrentPosition();
scanner.resetTo(scanner.getCurrentTokenStartPosition(), scannerEndPosition-1);
if (formatter.preferences.indent_statements_compare_to_block) {
unIndent();
}
formatClosingBrace(formatter.preferences.brace_position_for_block);
// scanner.resetTo(currentPosition, scannerEndPosition-1);
break;
}
case Token.tLPAREN:
++parenLevel;
print(currentToken.getLength(), hasWhitespace);
@ -902,14 +919,16 @@ public class Scribe {
// if we have a space between two tokens we ensure it will be dumped in
// the formatted string
int currentTokenStartPosition= scanner.getCurrentPosition();
if (shouldSkip(currentTokenStartPosition)) {
return false;
}
boolean hasComment= false;
boolean hasLineComment= false;
boolean hasWhitespace= false;
int count= 0;
while ((currentToken= scanner.nextToken()) != null) {
Position inactivePos= null;
if (skipOverInactive) {
inactivePos= getInactivePosAt(scanner.getCurrentTokenStartPosition());
Position inactivePos= getInactivePosAt(scanner.getCurrentTokenStartPosition());
if (inactivePos != null) {
int startOffset= Math.min(scanner.getCurrentTokenStartPosition(), inactivePos.getOffset());
int endOffset= Math.min(scannerEndPosition, inactivePos.getOffset() + inactivePos.getLength());
@ -1037,8 +1056,8 @@ public class Scribe {
* @return
*/
private Position getInactivePosAt(int offset) {
for (Iterator iter= fSkipPositions.iterator(); iter.hasNext();) {
Position pos= (Position) iter.next();
for (Iterator<Position> iter= fSkipPositions.iterator(); iter.hasNext();) {
Position pos= iter.next();
if (pos.includes(offset)) {
return pos;
}
@ -1220,23 +1239,15 @@ public class Scribe {
}
}
public void printNewLine() {
if (lastNumberOfNewLines >= 1) {
column= 1; // ensure that the scribe is at the beginning of a new
// line
return;
}
addInsertEdit(scanner.getCurrentTokenEndPosition() + 1, lineSeparator);
line++;
lastNumberOfNewLines= 1;
column= 1;
needSpace= false;
pendingSpace= false;
printNewLine(scanner.getCurrentTokenEndPosition() + 1);
}
public void printNewLine(int insertPosition) {
if (shouldSkip(insertPosition - 1)) {
return;
}
if (lastNumberOfNewLines >= 1) {
column= 1; // ensure that the scribe is at the beginning of a new
// line
column= 1; // ensure that the scribe is at the beginning of a new line
return;
}
addInsertEdit(insertPosition, lineSeparator);
@ -1253,6 +1264,10 @@ public class Scribe {
public void printNextToken(int expectedTokenType, boolean considerSpaceIfAny) {
printComment();
if (shouldSkip(scanner.getCurrentPosition())) {
// print(0, considerSpaceIfAny);
return;
}
currentToken= scanner.nextToken();
if (currentToken == null || expectedTokenType != currentToken.type) {
throw new AbortFormatting(
@ -1267,6 +1282,10 @@ public class Scribe {
public void printNextToken(int[] expectedTokenTypes, boolean considerSpaceIfAny) {
printComment();
if (shouldSkip(scanner.getCurrentPosition())) {
// print(0, considerSpaceIfAny);
return;
}
currentToken= scanner.nextToken();
if (Arrays.binarySearch(expectedTokenTypes, currentToken.type) < 0) {
StringBuffer expectations= new StringBuffer(5);
@ -1302,6 +1321,9 @@ public class Scribe {
// if we have a space between two tokens we ensure it will be dumped in
// the formatted string
int currentTokenStartPosition= scanner.getCurrentPosition();
if (shouldSkip(currentTokenStartPosition)) {
return;
}
boolean hasWhitespaces= false;
boolean hasComment= false;
boolean hasLineComment= false;
@ -1435,6 +1457,9 @@ public class Scribe {
public void space() {
if (!needSpace)
return;
if (shouldSkip(scanner.getCurrentPosition())) {
return;
}
lastNumberOfNewLines= 0;
pendingSpace= true;
column++;
@ -1470,6 +1495,10 @@ public class Scribe {
}
public void unIndent() {
if (shouldSkip(scanner.getCurrentPosition())) {
fSkippedIndentations--;
return;
}
indentationLevel-= indentationSize;
numberOfIndentations--;
}
@ -1477,8 +1506,11 @@ public class Scribe {
/**
*/
public void printModifiers() {
boolean isFirstModifier= true;
int currentTokenStartPosition= scanner.getCurrentPosition();
if (shouldSkip(currentTokenStartPosition)) {
return;
}
boolean isFirstModifier= true;
boolean hasComment= false;
while ((currentToken= scanner.nextToken()) != null) {
switch (currentToken.type) {
@ -1580,6 +1612,9 @@ public class Scribe {
*/
public boolean skipToToken(int expectedTokenType) {
int skipStart= scanner.getCurrentPosition();
if (shouldSkip(skipStart)) {
return true;
}
int braceLevel= 0;
int parenLevel= 0;
while ((currentToken= scanner.nextToken()) != null) {
@ -1634,4 +1669,44 @@ public class Scribe {
}
}
/**
* @param offset
* @return
*/
boolean shouldSkip(int offset) {
return offset >= fSkipTokensFrom && offset <= fSkipTokensTo;
}
public void skipRange(int offset, int endOffset) {
if (offset == fSkipTokensFrom) {
return;
}
final int currentPosition= scanner.getCurrentPosition();
if (currentPosition >= offset && currentPosition < endOffset) {
printRaw(offset, endOffset - offset);
}
fSkipTokensFrom= offset;
fSkipTokensTo= endOffset;
}
public void resetToOffset(int offset) {
if (fSkipTokensTo > 0) {
fSkipTokensFrom= Integer.MAX_VALUE;
fSkipTokensTo= 0;
while (fSkippedIndentations > 0) {
indent();
fSkippedIndentations--;
}
while (fSkippedIndentations < 0) {
unIndent();
fSkippedIndentations++;
}
if (offset > scanner.getCurrentPosition()) {
printRaw(scanner.getCurrentPosition(), offset - scanner.getCurrentPosition());
scanner.resetTo(offset, scannerEndPosition - 1);
}
}
}
}

View file

@ -53,3 +53,10 @@ void bug183220() {
}
}
}
// declaration with array initializer
long dummy[]= { 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100,
100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100,
100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100,
100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100,
100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100,
100, 100, 100, 100, 100, 100, 100, 100, 100, 100, };

View file

@ -28,3 +28,8 @@ void bug183220()
}
}
}
// declaration with array initializer
long dummy[]= { 100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,
100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,
100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,
};

View file

@ -58,7 +58,7 @@ public class CodeFormatterTest extends BaseUITestCase {
String before= contents[0].toString();
IDocument document= new Document(before);
String expected= contents[1].toString();
TextEdit edit= CodeFormatterUtil.format(CodeFormatter.K_COMPILATION_UNIT, before, 0, TextUtilities.getDefaultLineDelimiter(document), fOptions);
TextEdit edit= CodeFormatterUtil.format(CodeFormatter.K_TRANSLATION_UNIT, before, 0, TextUtilities.getDefaultLineDelimiter(document), fOptions);
assertNotNull(edit);
edit.apply(document);
assertEquals(expected, document.get());
@ -353,4 +353,43 @@ public class CodeFormatterTest extends BaseUITestCase {
assertFormatterResult();
}
//#define break_start(); { int foo;
//#define break_end(); foo = 0; }
//
//void break_indenter(int a, int b) {
// break_start(); // This semicolon moves to its own line.
// if(a > b) {
// indentation_remains();
// }
//
// if(b>a)
// indentation_vanishes();
//
// break_end();
//
// if(b == a)
// indentation_remains();
//}
//#define break_start(); { int foo;
//#define break_end(); foo = 0; }
//
//void break_indenter(int a, int b) {
// break_start()
// ; // This semicolon moves to its own line.
// if (a > b) {
// indentation_remains();
// }
//
// if (b>a)
// indentation_vanishes();
//
// break_end();
//
// if (b == a)
// indentation_remains();
//}
public void testBracesInMacros_Bug217435() throws Exception {
assertFormatterResult();
}
}