1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-04-29 19:45:01 +02:00

Fix formatter and highlighting issues with function-try-block

This commit is contained in:
Anton Leherbauer 2007-12-20 15:38:02 +00:00
parent d33cc23add
commit 8b966ae692
4 changed files with 279 additions and 40 deletions

View file

@ -92,6 +92,7 @@ import org.eclipse.cdt.core.dom.ast.c.ICASTEnumerationSpecifier;
import org.eclipse.cdt.core.dom.ast.c.ICASTPointer;
import org.eclipse.cdt.core.dom.ast.cpp.CPPASTVisitor;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCastExpression;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCatchHandler;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTConstructorChainInitializer;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTConstructorInitializer;
@ -112,6 +113,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateId;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateParameter;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateSpecialization;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplatedTypeTemplateParameter;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTryBlockStatement;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTUsingDeclaration;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTUsingDirective;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTVisiblityLabel;
@ -202,9 +204,11 @@ public class CodeFormatterVisitor extends CPPASTVisitor {
private String fTranslationUnitFile;
private boolean fInsideFor;
private boolean fExpectSemicolonAfterDeclaration= true;
private MultiStatus fStatus;
public CodeFormatterVisitor(DefaultCodeFormatterOptions preferences, Map settings, int offset, int length) {
localScanner = new Scanner() {
public Token nextToken() {
@ -465,9 +469,7 @@ public class CodeFormatterVisitor extends CPPASTVisitor {
}
if (node instanceof ICPPASTFunctionTryBlockDeclarator) {
visit((IASTStandardFunctionDeclarator)node);
skipNode(node);
return PROCESS_SKIP;
visit((ICPPASTFunctionTryBlockDeclarator)node);
} else if (node instanceof ICPPASTFunctionDeclarator) {
return visit((ICPPASTFunctionDeclarator)node);
} else if (node instanceof IASTStandardFunctionDeclarator) {
@ -586,6 +588,10 @@ public class CodeFormatterVisitor extends CPPASTVisitor {
} else if (node instanceof ICPPASTWhileStatement) {
// TLETODO [formatter] handle C++ specifics
visit((IASTWhileStatement)node);
} else if (node instanceof ICPPASTCatchHandler) {
visit((ICPPASTCatchHandler)node);
} else if (node instanceof ICPPASTTryBlockStatement) {
visit((ICPPASTTryBlockStatement)node);
} else if (node instanceof IASTWhileStatement) {
visit((IASTWhileStatement)node);
} else if (node instanceof IASTDoStatement) {
@ -858,6 +864,16 @@ public class CodeFormatterVisitor extends CPPASTVisitor {
}
scribe.printTrailingComment();
scribe.startNewLine();
// hack: catch handlers are part of declarator
if (decl instanceof ICPPASTFunctionTryBlockDeclarator) {
ICPPASTCatchHandler[] catchHandlers= ((ICPPASTFunctionTryBlockDeclarator)decl).getCatchHandlers();
for (int i= 0; i < catchHandlers.length; i++) {
catchHandlers[i].accept(this);
scribe.printTrailingComment();
scribe.startNewLine();
}
}
return PROCESS_SKIP;
}
@ -878,6 +894,13 @@ public class CodeFormatterVisitor extends CPPASTVisitor {
}
}
if (node instanceof ICPPASTFunctionTryBlockDeclarator) {
scribe.startNewLine();
scribe.printNextToken(Token.t_try, false);
scribe.printTrailingComment();
// for catch handlers @see #visit(IASTFunctionDefinition)
}
final ICPPASTConstructorChainInitializer[] constructorChain= node.getConstructorChain();
if (constructorChain != null && constructorChain.length > 0) {
// TLETODO [formatter] need special constructor chain alignment
@ -1044,11 +1067,13 @@ public class CodeFormatterVisitor extends CPPASTVisitor {
final ListAlignment align= new ListAlignment(Alignment.M_COMPACT_SPLIT);
formatList(declarators, align, false, false);
}
if (peekNextToken() != Token.tSEMI) {
scribe.skipToToken(Token.tSEMI);
if (fExpectSemicolonAfterDeclaration) {
if (peekNextToken() != Token.tSEMI) {
scribe.skipToToken(Token.tSEMI);
}
scribe.printNextToken(Token.tSEMI, preferences.insert_space_before_semicolon);
scribe.printTrailingComment();
}
scribe.printNextToken(Token.tSEMI, preferences.insert_space_before_semicolon);
scribe.printTrailingComment();
return PROCESS_SKIP;
}
@ -1355,6 +1380,49 @@ public class CodeFormatterVisitor extends CPPASTVisitor {
}
}
private int visit(ICPPASTTryBlockStatement node) {
scribe.printNextToken(Token.t_try, scribe.printComment());
final IASTStatement tryBody= node.getTryBody();
if (tryBody != null) {
tryBody.accept(this);
}
scribe.printTrailingComment();
ICPPASTCatchHandler[] catchHandlers= node.getCatchHandlers();
for (int i= 0; i < catchHandlers.length; i++) {
catchHandlers[i].accept(this);
scribe.printTrailingComment();
}
return PROCESS_SKIP;
}
private int visit(ICPPASTCatchHandler node) {
scribe.printNextToken(Token.t_catch, true);
scribe.printNextToken(Token.tLPAREN, /* preferences.insert_space_before_opening_paren_in_catch */ true);
if (/* preferences.insert_space_after_opening_paren_in_catch */ false) {
scribe.space();
}
final IASTDeclaration decl= node.getDeclaration();
if (decl != null) {
fExpectSemicolonAfterDeclaration= false;
try {
decl.accept(this);
} finally {
fExpectSemicolonAfterDeclaration= true;
}
} else if (node.isCatchAll()) {
scribe.printNextToken(Token.tELIPSE);
}
scribe.printNextToken(Token.tRPAREN, /* preferences.insert_space_before_closing_paren_in_catch */ false);
if (/* preferences.insert_space_after_closing_paren_in_catch */ true) {
scribe.space();
}
final IASTStatement catchBody= node.getCatchBody();
if (catchBody != null) {
catchBody.accept(this);
}
return PROCESS_SKIP;
}
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;

View file

@ -285,4 +285,58 @@ public class CodeFormatterTest extends BaseUITestCase {
assertFormatterResult();
}
//main
//(
// int argc,
// char const * argv[]
//)
//try
//{
// for ( int i = 1 ; i < argc ; ++i )
// {
// }
// return 0;
//}
//catch ( float e )
//{
// return 1;
//}
//catch ( ... )
//{
// return 2;
//}
//main(int argc, char const * argv[])
//try {
// for (int i = 1; i < argc; ++i) {
// }
// return 0;
//}
//catch (float e) {
// return 1;
//}
//catch (...) {
// return 2;
//}
public void testFunctionTryCatchBlock() throws Exception {
assertFormatterResult();
}
//main(int argc, char const * argv[]) { try { for (int i = 1; i < argc; ++i) { } return 0; } catch (float e) { return 1; } catch (...) { return 2; } }
//main(int argc, char const * argv[]) {
// try {
// for (int i = 1; i < argc; ++i) {
// }
// return 0;
// } catch (float e) {
// return 1;
// } catch (...) {
// return 2;
// }
//}
public void testTryCatchBlock() throws Exception {
assertFormatterResult();
}
}

View file

@ -33,17 +33,26 @@ import org.eclipse.cdt.core.dom.ast.IASTDeclSpecifier;
import org.eclipse.cdt.core.dom.ast.IASTDeclaration;
import org.eclipse.cdt.core.dom.ast.IASTDeclarator;
import org.eclipse.cdt.core.dom.ast.IASTExpression;
import org.eclipse.cdt.core.dom.ast.IASTFileLocation;
import org.eclipse.cdt.core.dom.ast.IASTFunctionDefinition;
import org.eclipse.cdt.core.dom.ast.IASTImageLocation;
import org.eclipse.cdt.core.dom.ast.IASTInitializer;
import org.eclipse.cdt.core.dom.ast.IASTMacroExpansion;
import org.eclipse.cdt.core.dom.ast.IASTName;
import org.eclipse.cdt.core.dom.ast.IASTNode;
import org.eclipse.cdt.core.dom.ast.IASTNodeLocation;
import org.eclipse.cdt.core.dom.ast.IASTParameterDeclaration;
import org.eclipse.cdt.core.dom.ast.IASTPreprocessorMacroDefinition;
import org.eclipse.cdt.core.dom.ast.IASTProblem;
import org.eclipse.cdt.core.dom.ast.IASTStatement;
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
import org.eclipse.cdt.core.dom.ast.IASTTypeId;
import org.eclipse.cdt.core.dom.ast.IASTEnumerationSpecifier.IASTEnumerator;
import org.eclipse.cdt.core.dom.ast.cpp.CPPASTVisitor;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCatchHandler;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionTryBlockDeclarator;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNamespaceDefinition;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateParameter;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier.ICPPASTBaseSpecifier;
import org.eclipse.cdt.core.model.ICElement;
import org.eclipse.cdt.core.model.ILanguage;
import org.eclipse.cdt.ui.CUIPlugin;
@ -63,10 +72,92 @@ import org.eclipse.cdt.internal.ui.text.ICReconcilingListener;
*/
public class SemanticHighlightingReconciler implements ICReconcilingListener {
/**
* AST visitor to test whether a node is a leaf node.
*/
public static final class LeafNodeTester extends CPPASTVisitor {
{
shouldVisitNames= true;
shouldVisitDeclarations= true;
shouldVisitInitializers= true;
shouldVisitParameterDeclarations= true;
shouldVisitDeclarators= true;
shouldVisitDeclSpecifiers= true;
shouldVisitExpressions= true;
shouldVisitStatements= true;
shouldVisitTypeIds= true;
shouldVisitEnumerators= true;
shouldVisitTranslationUnit= false;
shouldVisitProblems= true;
shouldVisitComments= false;
shouldVisitBaseSpecifiers= true;
shouldVisitNamespaces= true;
shouldVisitTemplateParameters= true;
}
private int fVisits;
private int processNode(IASTNode node) {
if (++fVisits > 1)
return PROCESS_ABORT;
return PROCESS_CONTINUE;
}
public int visit(ICPPASTBaseSpecifier specifier) {
return processNode(specifier);
}
public int visit(ICPPASTNamespaceDefinition namespace) {
return processNode(namespace);
}
public int visit(ICPPASTTemplateParameter parameter) {
return processNode(parameter);
}
public int visit(IASTDeclaration declaration) {
return processNode(declaration);
}
public int visit(IASTDeclarator declarator) {
return processNode(declarator);
}
public int visit(IASTDeclSpecifier declSpec) {
return processNode(declSpec);
}
public int visit(IASTEnumerator enumerator) {
return processNode(enumerator);
}
public int visit(IASTExpression expression) {
return processNode(expression);
}
public int visit(IASTInitializer initializer) {
return processNode(initializer);
}
public int visit(IASTName name) {
return processNode(name);
}
public int visit(IASTParameterDeclaration parameterDeclaration) {
return processNode(parameterDeclaration);
}
public int visit(IASTProblem problem) {
return processNode(problem);
}
public int visit(IASTStatement statement) {
return processNode(statement);
}
public int visit(IASTTranslationUnit tu) {
return processNode(tu);
}
public int visit(IASTTypeId typeId) {
return processNode(typeId);
}
public boolean isLeafNode(IASTNode node) {
fVisits= 0;
node.accept(this);
return fVisits <= 1;
}
}
/**
* Collects positions from the AST.
*/
private class PositionCollector extends CPPASTVisitor {
{
shouldVisitTranslationUnit= true;
shouldVisitNames= true;
@ -77,11 +168,13 @@ public class SemanticHighlightingReconciler implements ICReconcilingListener {
shouldVisitDeclarators= true;
shouldVisitNamespaces= true;
}
private boolean shouldVisitCatchHandlers= true;
/** The semantic token */
private SemanticToken fToken= new SemanticToken();
private String fFilePath;
private int fMinLocation;
private final LeafNodeTester fgLeafNodeTester= new LeafNodeTester();
/**
* @param filePath
@ -100,7 +193,7 @@ public class SemanticHighlightingReconciler implements ICReconcilingListener {
for (int i= 0; i < macroDefs.length; i++) {
IASTPreprocessorMacroDefinition macroDef= macroDefs[i];
if (fFilePath.equals(macroDef.getContainingFilename())) {
visit(macroDef.getName());
visitNode(macroDef.getName());
}
}
// TODO visit macro expansions
@ -127,6 +220,22 @@ public class SemanticHighlightingReconciler implements ICReconcilingListener {
return PROCESS_CONTINUE;
}
/*
* @see org.eclipse.cdt.core.dom.ast.ASTVisitor#leave(org.eclipse.cdt.core.dom.ast.IASTDeclaration)
*/
public int leave(IASTDeclaration declaration) {
if (!shouldVisitCatchHandlers && declaration instanceof IASTFunctionDefinition) {
shouldVisitCatchHandlers= true;
IASTFunctionDefinition functionDef= (IASTFunctionDefinition) declaration;
ICPPASTFunctionTryBlockDeclarator declarator= (ICPPASTFunctionTryBlockDeclarator) functionDef.getDeclarator();
ICPPASTCatchHandler[] catchHandlers= declarator.getCatchHandlers();
for (int i = 0; i < catchHandlers.length; i++) {
catchHandlers[i].accept(this);
}
}
return PROCESS_CONTINUE;
}
/*
* @see org.eclipse.cdt.core.dom.ast.cpp.CPPASTVisitor#visit(org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNamespaceDefinition)
*/
@ -157,6 +266,9 @@ public class SemanticHighlightingReconciler implements ICReconcilingListener {
if (checkForMacro(declarator)) {
return PROCESS_SKIP;
}
if (declarator instanceof ICPPASTFunctionTryBlockDeclarator) {
shouldVisitCatchHandlers= false;
}
return PROCESS_CONTINUE;
}
@ -174,6 +286,9 @@ public class SemanticHighlightingReconciler implements ICReconcilingListener {
* @see org.eclipse.cdt.core.dom.ast.ASTVisitor#visit(org.eclipse.cdt.core.dom.ast.IASTStatement)
*/
public int visit(IASTStatement statement) {
if (!shouldVisitCatchHandlers && statement instanceof ICPPASTCatchHandler) {
return PROCESS_SKIP;
}
if (checkForMacro(statement)) {
return PROCESS_SKIP;
}
@ -194,35 +309,42 @@ public class SemanticHighlightingReconciler implements ICReconcilingListener {
}
private boolean checkForMacro(IASTNode node) {
boolean isLeafNode= isLeafNode(node);
IASTNodeLocation[] nodeLocations= node.getNodeLocations();
if (nodeLocations.length == 1 && nodeLocations[0] instanceof IASTMacroExpansion) {
IASTNodeLocation useLocation= getMinFileLocation(nodeLocations);
if (useLocation != null) {
final int useOffset = useLocation.getNodeOffset();
if (useOffset <= fMinLocation) {
// performance: we had that macro expansion already
return false;
}
fMinLocation= useOffset;
// TLETODO This does not work correctly for nested macro substitutions
IASTPreprocessorMacroDefinition macroDef= ((IASTMacroExpansion)nodeLocations[0]).getMacroDefinition();
final int macroLength;
IASTNodeLocation defLocation= macroDef.getName().getFileLocation();
if (defLocation != null) {
macroLength= defLocation.getNodeLength();
} else {
macroLength= macroDef.getName().toCharArray().length;
}
IASTNode macroNode= node.getTranslationUnit().selectNodeForLocation(fFilePath, useOffset, macroLength);
if (macroNode != null && visitMacro(macroNode, macroLength)) {
fMinLocation= useOffset + macroLength;
return false;
for (int i= 0; i < nodeLocations.length; i++) {
IASTNodeLocation nodeLocation= nodeLocations[i];
if (nodeLocation instanceof IASTMacroExpansion) {
IASTNodeLocation useLocation= nodeLocation.asFileLocation();
if (useLocation != null) {
final int useOffset = useLocation.getNodeOffset();
if (useOffset > fMinLocation) {
fMinLocation= useOffset;
IASTPreprocessorMacroDefinition macroDef= ((IASTMacroExpansion)nodeLocation).getMacroDefinition();
final int macroLength;
IASTNodeLocation defLocation= macroDef.getName().getFileLocation();
if (defLocation != null) {
macroLength= defLocation.getNodeLength();
} else {
macroLength= macroDef.getName().toCharArray().length;
}
IASTNode macroNode= node.getTranslationUnit().selectNodeForLocation(fFilePath, useOffset, macroLength);
if (macroNode != null && visitMacro(macroNode, macroLength)) {
fMinLocation= useOffset + macroLength;
}
}
}
}
if (!isLeafNode) {
break;
}
}
return false;
}
private boolean isLeafNode(IASTNode node) {
return fgLeafNodeTester.isLeafNode(node);
}
private boolean visitMacro(IASTNode node, int macroLength) {
fToken.update(node);
for (int i= 0, n= fJobSemanticHighlightings.length; i < n; ++i) {
@ -318,14 +440,6 @@ public class SemanticHighlightingReconciler implements ICReconcilingListener {
}
}
private IASTFileLocation getMinFileLocation(IASTNodeLocation[] locations) {
if (locations == null || locations.length == 0) {
return null;
}
final IASTNodeLocation nodeLocation= locations[0];
return nodeLocation.asFileLocation();
}
/**
* Add a position with the given range and highlighting iff it does not exist already.
*

View file

@ -1640,6 +1640,9 @@ public class SemanticHighlightings {
if (node instanceof IASTProblem) {
return true;
}
if (node instanceof ICPPASTQualifiedName || node instanceof ICPPASTTemplateId) {
return false;
}
IBinding binding= token.getBinding();
if (binding instanceof IProblemBinding) {
return true;