aboutsummaryrefslogtreecommitdiffstats
path: root/src/plugins/cpptools/cppchecksymbols.cpp
diff options
context:
space:
mode:
authorFrancois Ferrand <[email protected]>2010-10-18 17:45:49 +0200
committerErik Verbruggen <[email protected]>2012-03-29 14:53:48 +0200
commite639a2381fd755819cb93992c66dca03bb225f83 (patch)
tree31a9655a7c3baf18e77a4090318659fb975481e2 /src/plugins/cpptools/cppchecksymbols.cpp
parent6c24b8b74075807e48d27d1be052d6f7d4950540 (diff)
CppHighlighter: highlight all functions/methods.
- Highlight all function/methods (not just virtual methods). - Highlight as a function even if number of arguments does not match. In that case, add a diagnostic message to indicate there are too many/too few arguments. - Fix highlighting of parameters in function declarations. These used to be handled indiferently, and they could be mistaken for type or field references. - Properly highlight template method calls. Change-Id: I6ab463996dda47554839f482da47f561f76663a7 Reviewed-by: Erik Verbruggen <[email protected]>
Diffstat (limited to 'src/plugins/cpptools/cppchecksymbols.cpp')
-rw-r--r--src/plugins/cpptools/cppchecksymbols.cpp98
1 files changed, 84 insertions, 14 deletions
diff --git a/src/plugins/cpptools/cppchecksymbols.cpp b/src/plugins/cpptools/cppchecksymbols.cpp
index a2d1d6dcf07..2330e037c03 100644
--- a/src/plugins/cpptools/cppchecksymbols.cpp
+++ b/src/plugins/cpptools/cppchecksymbols.cpp
@@ -68,6 +68,7 @@ class CollectSymbols: protected SymbolVisitor
Snapshot _snapshot;
QSet<QByteArray> _types;
QSet<QByteArray> _members;
+ QSet<QByteArray> _functions;
QSet<QByteArray> _virtualMethods;
QSet<QByteArray> _statics;
bool _mainDocument;
@@ -90,6 +91,11 @@ public:
return _members;
}
+ const QSet<QByteArray> &functions() const
+ {
+ return _functions;
+ }
+
const QSet<QByteArray> &virtualMethods() const
{
return _virtualMethods;
@@ -149,6 +155,17 @@ protected:
}
}
+ void addFunction(const Name *name)
+ {
+ if (! name) {
+ return;
+
+ } else if (name->isNameId()) {
+ const Identifier *id = name->identifier();
+ _functions.insert(QByteArray::fromRawData(id->chars(), id->size()));
+ }
+ }
+
void addVirtualMethod(const Name *name)
{
if (! name) {
@@ -183,6 +200,8 @@ protected:
{
if (symbol->isVirtual())
addVirtualMethod(symbol->name());
+ else
+ addFunction(symbol->name());
return true;
}
@@ -206,6 +225,8 @@ protected:
if (Function *funTy = symbol->type()->asFunctionType()) {
if (funTy->isVirtual())
addVirtualMethod(symbol->name());
+ else
+ addFunction(symbol->name());
}
if (symbol->isTypedef())
@@ -300,6 +321,7 @@ CheckSymbols::CheckSymbols(Document::Ptr doc, const LookupContext &context)
_fileName = doc->fileName();
_potentialTypes = collectTypes.types();
_potentialMembers = collectTypes.members();
+ _potentialFunctions = collectTypes.functions();
_potentialVirtualMethods = collectTypes.virtualMethods();
_potentialStatics = collectTypes.statics();
@@ -326,7 +348,7 @@ void CheckSymbols::run()
bool CheckSymbols::warning(unsigned line, unsigned column, const QString &text, unsigned length)
{
Document::DiagnosticMessage m(Document::DiagnosticMessage::Warning, _fileName, line, column, text, length);
- _diagnosticMessages.append(m);
+ _doc->addDiagnosticMessage(m);
return false;
}
@@ -477,6 +499,8 @@ bool CheckSymbols::visit(SimpleDeclarationAST *ast)
addUse(declId, SemanticInfo::VirtualMethodUse);
} else if (maybeVirtualMethod(decl->name())) {
addVirtualMethod(_context.lookup(decl->name(), decl->enclosingScope()), declId, funTy->argumentCount());
+ } else {
+ addUse(declId, SemanticInfo::FunctionUse);
}
}
}
@@ -535,7 +559,7 @@ bool CheckSymbols::visit(CallAST *ast)
if (MemberAccessAST *access = ast->base_expression->asMemberAccess()) {
if (access->member_name && access->member_name->name) {
- if (maybeVirtualMethod(access->member_name->name)) {
+ if (maybeVirtualMethod(access->member_name->name) || maybeFunction(access->member_name->name)) {
const QByteArray expression = textOf(access);
const QList<LookupItem> candidates =
@@ -551,7 +575,7 @@ bool CheckSymbols::visit(CallAST *ast)
}
} else if (IdExpressionAST *idExpr = ast->base_expression->asIdExpression()) {
if (const Name *name = idExpr->name->name) {
- if (maybeVirtualMethod(name)) {
+ if (maybeVirtualMethod(name) || maybeFunction(name)) {
NameAST *exprName = idExpr->name;
if (QualifiedNameAST *q = exprName->asQualifiedName())
exprName = q->unqualified_name;
@@ -651,6 +675,8 @@ void CheckSymbols::checkName(NameAST *ast, Scope *scope)
Class *klass = scope->asClass();
if (hasVirtualDestructor(_context.lookupType(klass)))
addUse(ast, SemanticInfo::VirtualMethodUse);
+ else
+ addUse(ast, SemanticInfo::FunctionUse);
} else if (maybeType(ast->name) || maybeStatic(ast->name)) {
const QList<LookupItem> candidates = _context.lookup(ast->name, scope);
addTypeOrStatic(candidates, ast);
@@ -679,6 +705,14 @@ bool CheckSymbols::visit(DestructorNameAST *ast)
return true;
}
+bool CheckSymbols::visit(ParameterDeclarationAST *ast)
+{
+ accept(ast->type_specifier_list);
+ // Skip parameter name, it does not need to be colored
+ accept(ast->expression);
+ return false;
+}
+
bool CheckSymbols::visit(QualifiedNameAST *ast)
{
if (ast->name) {
@@ -722,6 +756,8 @@ bool CheckSymbols::visit(QualifiedNameAST *ast)
if (ast->unqualified_name->asDestructorName() != 0) {
if (hasVirtualDestructor(binding))
addUse(ast->unqualified_name, SemanticInfo::VirtualMethodUse);
+ else
+ addUse(ast->unqualified_name, SemanticInfo::FunctionUse);
} else {
addTypeOrStatic(binding->find(ast->unqualified_name->name), ast->unqualified_name);
}
@@ -802,6 +838,8 @@ bool CheckSymbols::visit(FunctionDefinitionAST *ast)
addUse(declId, SemanticInfo::VirtualMethodUse);
} else if (maybeVirtualMethod(fun->name())) {
addVirtualMethod(_context.lookup(fun->name(), fun->enclosingScope()), declId, fun->argumentCount());
+ } else {
+ addUse(declId, SemanticInfo::FunctionUse);
}
}
}
@@ -1023,30 +1061,49 @@ void CheckSymbols::addVirtualMethod(const QList<LookupItem> &candidates, NameAST
if (tok.generated())
return;
+ enum { Match_None, Match_TooManyArgs, Match_TooFewArgs, Match_Ok } matchType = Match_None;
+ SemanticInfo::UseKind kind = SemanticInfo::FunctionUse;
foreach (const LookupItem &r, candidates) {
Symbol *c = r.declaration();
if (! c)
continue;
- Function *funTy = r.type()->asFunctionType();
+ Function *funTy = c->type()->asFunctionType();
+ if (! funTy) {
+ //Try to find a template function
+ if (Template * t = r.type()->asTemplateType())
+ if ((c = t->declaration()))
+ funTy = c->type()->asFunctionType();
+ }
if (! funTy)
- continue;
- if (! funTy->isVirtual())
- continue;
- else if (argumentCount < funTy->minimumArgumentCount())
- continue;
- else if (argumentCount > funTy->argumentCount()) {
- if (! funTy->isVariadic())
- continue;
+ continue; // TODO: add diagnostic messages and color call-operators calls too?
+
+ kind = funTy->isVirtual() ? SemanticInfo::VirtualMethodUse : SemanticInfo::FunctionUse;
+ if (argumentCount < funTy->minimumArgumentCount()) {
+ matchType = Match_TooFewArgs;
+ }
+ else if (argumentCount > funTy->argumentCount() && ! funTy->isVariadic()) {
+ matchType = Match_TooManyArgs;
+ }
+ else {
+ matchType = Match_Ok;
+ break;
}
+ }
+ if (matchType != Match_None) {
unsigned line, column;
getTokenStartPosition(startToken, &line, &column);
const unsigned length = tok.length();
- const Use use(line, column, length, SemanticInfo::VirtualMethodUse);
+ // Add a diagnostic message if argument count does not match
+ if (matchType == Match_TooFewArgs)
+ warning(line, column, "Too few arguments", length);
+ else if (matchType == Match_TooManyArgs)
+ warning(line, column, "Too many arguments", length);
+
+ const Use use(line, column, length, kind);
addUse(use);
- break;
}
}
@@ -1120,6 +1177,19 @@ static bool sortByLinePredicate(const CheckSymbols::Use &lhs, const CheckSymbols
return lhs.line < rhs.line;
}
+bool CheckSymbols::maybeFunction(const Name *name) const
+{
+ if (name) {
+ if (const Identifier *ident = name->identifier()) {
+ const QByteArray id = QByteArray::fromRawData(ident->chars(), ident->size());
+ if (_potentialFunctions.contains(id))
+ return true;
+ }
+ }
+
+ return false;
+}
+
void CheckSymbols::flush()
{
_lineOfLastUsage = 0;