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:
parent
d33cc23add
commit
8b966ae692
4 changed files with 279 additions and 40 deletions
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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,9 +266,12 @@ public class SemanticHighlightingReconciler implements ICReconcilingListener {
|
|||
if (checkForMacro(declarator)) {
|
||||
return PROCESS_SKIP;
|
||||
}
|
||||
if (declarator instanceof ICPPASTFunctionTryBlockDeclarator) {
|
||||
shouldVisitCatchHandlers= false;
|
||||
}
|
||||
return PROCESS_CONTINUE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* @see org.eclipse.cdt.core.dom.ast.ASTVisitor#visit(org.eclipse.cdt.core.dom.ast.IASTExpression)
|
||||
*/
|
||||
|
@ -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.
|
||||
*
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Add table
Reference in a new issue