diff options
Diffstat (limited to 'src/plugins/cppeditor/cppchecksymbols.cpp')
-rw-r--r-- | src/plugins/cppeditor/cppchecksymbols.cpp | 115 |
1 files changed, 109 insertions, 6 deletions
diff --git a/src/plugins/cppeditor/cppchecksymbols.cpp b/src/plugins/cppeditor/cppchecksymbols.cpp index 635ddb6285..f33c6bdf46 100644 --- a/src/plugins/cppeditor/cppchecksymbols.cpp +++ b/src/plugins/cppeditor/cppchecksymbols.cpp @@ -28,6 +28,8 @@ **************************************************************************/ #include "cppchecksymbols.h" +#include "cpplocalsymbols.h" + #include <cplusplus/Overview.h> #include <Names.h> @@ -45,6 +47,7 @@ #include <qtconcurrent/runextensions.h> using namespace CPlusPlus; +using namespace CppEditor::Internal; namespace { @@ -53,6 +56,7 @@ class CollectTypes: protected SymbolVisitor Document::Ptr _doc; Snapshot _snapshot; QSet<QByteArray> _types; + QSet<QByteArray> _members; QList<ScopedSymbol *> _scopes; QList<NameAST *> _names; bool _mainDocument; @@ -70,6 +74,11 @@ public: return _types; } + const QSet<QByteArray> &members() const + { + return _members; + } + const QList<ScopedSymbol *> &scopes() const { return _scopes; @@ -126,6 +135,18 @@ protected: } } + void addMember(const Name *name) + { + if (! name) { + return; + + } else if (name->isNameId()) { + const Identifier *id = name->identifier(); + _members.insert(QByteArray::fromRawData(id->chars(), id->size())); + + } + } + void addScope(ScopedSymbol *symbol) { if (_mainDocument) @@ -166,6 +187,8 @@ protected: { if (symbol->isTypedef()) addType(symbol->name()); + else if (! symbol->type()->isFunctionType() && symbol->enclosingSymbol()->isClass()) + addMember(symbol->name()); return true; } @@ -267,6 +290,7 @@ CheckSymbols::CheckSymbols(Document::Ptr doc, const LookupContext &context) _fileName = doc->fileName(); CollectTypes collectTypes(doc, context.snapshot()); _potentialTypes = collectTypes.types(); + _potentialMembers = collectTypes.members(); _scopes = collectTypes.scopes(); _flushRequested = false; _flushLine = 0; @@ -351,6 +375,12 @@ bool CheckSymbols::visit(NamedTypeSpecifierAST *) return true; } +bool CheckSymbols::visit(MemberAccessAST *ast) +{ + accept(ast->base_expression); + return false; +} + void CheckSymbols::checkNamespace(NameAST *name) { if (! name) @@ -380,6 +410,28 @@ void CheckSymbols::checkName(NameAST *ast) Scope *scope = findScope(ast); const QList<Symbol *> candidates = _context.lookup(ast->name, scope); addTypeUsage(candidates, ast); + } else if (_potentialMembers.contains(id)) { + Scope *scope = findScope(ast); + const QList<Symbol *> candidates = _context.lookup(ast->name, scope); + addMemberUsage(candidates, ast); + } + } + } +} + +void CheckSymbols::checkMemberName(NameAST *ast) +{ + if (ast && ast->name) { + if (const Identifier *ident = ast->name->identifier()) { + const QByteArray id = QByteArray::fromRawData(ident->chars(), ident->size()); + if (_potentialMembers.contains(id)) { + Scope *scope = findScope(ast); + const QList<Symbol *> candidates = _context.lookup(ast->name, scope); + addMemberUsage(candidates, ast); + } else if (_potentialMembers.contains(id)) { + Scope *scope = findScope(ast); + const QList<Symbol *> candidates = _context.lookup(ast->name, scope); + addMemberUsage(candidates, ast); } } } @@ -473,14 +525,35 @@ void CheckSymbols::endVisit(TemplateDeclarationAST *) _templateDeclarationStack.takeFirst(); } +bool CheckSymbols::visit(FunctionDefinitionAST *ast) +{ + _functionDefinitionStack.append(ast); + const LocalSymbols locals(_doc, ast); + QList<SemanticInfo::Use> uses; + foreach (uses, locals.uses) { + foreach (const SemanticInfo::Use &u, uses) + addTypeUsage(u); + } + + accept(ast->decl_specifier_list); + accept(ast->declarator); + accept(ast->ctor_initializer); + accept(ast->function_body); + + _functionDefinitionStack.removeLast(); + return false; +} + void CheckSymbols::addTypeUsage(const Use &use) { - if (_typeUsages.size() >= 50) { - if (_flushRequested && use.line != _flushLine) - flush(); - else if (! _flushRequested) { - _flushRequested = true; - _flushLine = use.line; + if (_functionDefinitionStack.isEmpty()) { + if (_typeUsages.size() >= 50) { + if (_flushRequested && use.line != _flushLine) + flush(); + else if (! _flushRequested) { + _flushRequested = true; + _flushLine = use.line; + } } } @@ -538,6 +611,36 @@ void CheckSymbols::addTypeUsage(const QList<Symbol *> &candidates, NameAST *ast) } } +void CheckSymbols::addMemberUsage(const QList<Symbol *> &candidates, NameAST *ast) +{ + unsigned startToken = ast->firstToken(); + if (DestructorNameAST *dtor = ast->asDestructorName()) + startToken = dtor->identifier_token; + + const Token &tok = tokenAt(startToken); + if (tok.generated()) + return; + + unsigned line, column; + getTokenStartPosition(startToken, &line, &column); + const unsigned length = tok.length(); + + foreach (Symbol *c, candidates) { + if (! c->isDeclaration()) + continue; + else if (c->isTypedef()) + continue; + else if (c->type()->isFunctionType()) + continue; + else if (! c->enclosingSymbol()->isClass()) + continue; + + const Use use(line, column, length, Use::Field); + addTypeUsage(use); + //qDebug() << "added use" << oo(ast->name) << line << column << length; + } +} + unsigned CheckSymbols::startOfTemplateDeclaration(TemplateDeclarationAST *ast) const { if (ast->declaration) { |