diff options
author | Francois Ferrand <[email protected]> | 2010-10-18 17:45:49 +0200 |
---|---|---|
committer | Erik Verbruggen <[email protected]> | 2012-03-29 14:53:48 +0200 |
commit | e639a2381fd755819cb93992c66dca03bb225f83 (patch) | |
tree | 31a9655a7c3baf18e77a4090318659fb975481e2 /src/plugins/cpptools/cppchecksymbols.cpp | |
parent | 6c24b8b74075807e48d27d1be052d6f7d4950540 (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.cpp | 98 |
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; |