From 7e0e62cb253dbf26166d4dfaada1898beadc44ef Mon Sep 17 00:00:00 2001 From: Roberto Raggi Date: Wed, 7 Oct 2009 16:11:42 +0200 Subject: [PATCH] Find the canonical virtual method. --- src/libs/cplusplus/LookupContext.cpp | 111 +++++++++++++++++---- src/libs/cplusplus/LookupContext.h | 13 ++- src/plugins/cppeditor/cppeditor.cpp | 6 +- src/plugins/cpptools/cppfindreferences.cpp | 5 +- src/plugins/cpptools/cppmodelmanager.cpp | 3 +- 5 files changed, 110 insertions(+), 28 deletions(-) diff --git a/src/libs/cplusplus/LookupContext.cpp b/src/libs/cplusplus/LookupContext.cpp index 192d389fe2..0b2fd4bba2 100644 --- a/src/libs/cplusplus/LookupContext.cpp +++ b/src/libs/cplusplus/LookupContext.cpp @@ -30,6 +30,7 @@ #include "LookupContext.h" #include "ResolveExpression.h" #include "Overview.h" +#include "CppBindings.h" #include #include @@ -501,6 +502,97 @@ void LookupContext::expand(Scope *scope, } } +static void visibleClassBindings_helper(ClassBinding *classBinding, + QList *allClassBindings, + QSet *processed) +{ + if (! classBinding) + return; + + else if (processed->contains(classBinding)) + return; + + processed->insert(classBinding); + + foreach (ClassBinding *baseClassBinding, classBinding->baseClassBindings) + visibleClassBindings_helper(baseClassBinding, allClassBindings, processed); + + allClassBindings->append(classBinding); +} + +static QList visibleClassBindings(Symbol *symbol, NamespaceBinding *globalNamespace) +{ + QList classBindings; + + if (! symbol) + return classBindings; + + else if (Class *klass = symbol->asClass()) { + QSet processed; + + visibleClassBindings_helper(NamespaceBinding::find(klass, globalNamespace), + &classBindings, &processed); + } + + return classBindings; +} + +Symbol *LookupContext::canonicalSymbol(Symbol *symbol, + NamespaceBinding *globalNamespace) +{ + Symbol *canonicalSymbol = LookupContext::canonicalSymbol(symbol); + + if (Identifier *symbolId = canonicalSymbol->identifier()) { + if (symbolId && canonicalSymbol->type()->isFunctionType()) { + Class *enclosingClass = canonicalSymbol->scope()->owner()->asClass(); + const QList classBindings = visibleClassBindings(enclosingClass, globalNamespace); + + foreach (ClassBinding *baseClassBinding, classBindings) { + if (! baseClassBinding) + continue; + + foreach (Class *baseClass, baseClassBinding->symbols) { + if (! baseClass) + continue; + + for (Symbol *c = baseClass->members()->lookat(symbolId); c; c = c->next()) { + if (! symbolId->isEqualTo(c->identifier())) + continue; + else if (Function *f = c->type()->asFunctionType()) { + if (f->isVirtual()) + return LookupContext::canonicalSymbol(f); + } + } + } + } + } + } + + return canonicalSymbol; +} + +Symbol *LookupContext::canonicalSymbol(const QList &candidates, + NamespaceBinding *globalNamespaceBinding) +{ + if (candidates.isEmpty()) + return 0; + + return canonicalSymbol(candidates.first(), globalNamespaceBinding); +} + +Symbol *LookupContext::canonicalSymbol(const QList > &results, + NamespaceBinding *globalNamespaceBinding) +{ + QList candidates; + QPair result; + + foreach (result, results) + candidates.append(result.second); // ### not exacly. + + return canonicalSymbol(candidates, globalNamespaceBinding); +} + + Symbol *LookupContext::canonicalSymbol(Symbol *symbol) { Symbol *canonical = symbol; @@ -531,22 +623,3 @@ Symbol *LookupContext::canonicalSymbol(Symbol *symbol) return canonical; } - -Symbol *LookupContext::canonicalSymbol(const QList &candidates) -{ - if (candidates.isEmpty()) - return 0; - - return canonicalSymbol(candidates.first()); -} - -Symbol *LookupContext::canonicalSymbol(const QList > &results) -{ - QList candidates; - QPair result; - - foreach (result, results) - candidates.append(result.second); // ### not exacly. - - return canonicalSymbol(candidates); -} diff --git a/src/libs/cplusplus/LookupContext.h b/src/libs/cplusplus/LookupContext.h index bb5b053926..5424da869c 100644 --- a/src/libs/cplusplus/LookupContext.h +++ b/src/libs/cplusplus/LookupContext.h @@ -54,9 +54,14 @@ public: Document::Ptr document(const QString &fileName) const; Snapshot snapshot() const; - static Symbol *canonicalSymbol(Symbol *symbol); - static Symbol *canonicalSymbol(const QList &candidates); - static Symbol *canonicalSymbol(const QList > &candidates); // ### FIXME + static Symbol *canonicalSymbol(const QList &candidates, + NamespaceBinding *globalNamespaceBinding); + + static Symbol *canonicalSymbol(Symbol *symbol, + NamespaceBinding *globalNamespaceBinding); + + static Symbol *canonicalSymbol(const QList > &candidates, + NamespaceBinding *globalNamespaceBinding); QList resolve(Name *name) const { return resolve(name, visibleScopes()); } @@ -126,6 +131,8 @@ public: QList *expandedScopes) const; private: + static Symbol *canonicalSymbol(Symbol *symbol); + QList resolveQualifiedNameId(QualifiedNameId *q, const QList &visibleScopes, ResolveMode mode) const; diff --git a/src/plugins/cppeditor/cppeditor.cpp b/src/plugins/cppeditor/cppeditor.cpp index 13228855f9..eeda79c9e1 100644 --- a/src/plugins/cppeditor/cppeditor.cpp +++ b/src/plugins/cppeditor/cppeditor.cpp @@ -58,6 +58,7 @@ #include #include #include +#include #include @@ -838,8 +839,6 @@ CPlusPlus::Symbol *CPPEditor::findCanonicalSymbol(const QTextCursor &cursor, const QString code = expressionUnderCursor(tc); // qDebug() << "code:" << code; - const QString fileName = const_cast(this)->file()->fileName(); - TypeOfExpression typeOfExpression; typeOfExpression.setSnapshot(snapshot); @@ -849,7 +848,8 @@ CPlusPlus::Symbol *CPPEditor::findCanonicalSymbol(const QTextCursor &cursor, lastVisibleSymbol, TypeOfExpression::Preprocess); - Symbol *canonicalSymbol = LookupContext::canonicalSymbol(results); + NamespaceBindingPtr glo = bind(doc, snapshot); + Symbol *canonicalSymbol = LookupContext::canonicalSymbol(results, glo.data()); return canonicalSymbol; } diff --git a/src/plugins/cpptools/cppfindreferences.cpp b/src/plugins/cpptools/cppfindreferences.cpp index 40259589a2..9fab349368 100644 --- a/src/plugins/cpptools/cppfindreferences.cpp +++ b/src/plugins/cpptools/cppfindreferences.cpp @@ -152,7 +152,8 @@ protected: bool checkCandidates(const QList &candidates) const { - if (Symbol *canonicalSymbol = LookupContext::canonicalSymbol(candidates)) { + if (Symbol *canonicalSymbol = LookupContext::canonicalSymbol(candidates, _globalNamespaceBinding.data())) { + #if 0 qDebug() << "*** canonical symbol:" << canonicalSymbol->fileName() << canonicalSymbol->line() << canonicalSymbol->column() @@ -498,7 +499,7 @@ static void find_helper(QFutureInterface &future, files += snapshot.dependsOn(sourceFile); } - qDebug() << "done in:" << tm.elapsed() << "number of files to parse:" << files.size(); + //qDebug() << "done in:" << tm.elapsed() << "number of files to parse:" << files.size(); future.setProgressRange(0, files.size()); diff --git a/src/plugins/cpptools/cppmodelmanager.cpp b/src/plugins/cpptools/cppmodelmanager.cpp index 56e7b1d48f..89df8fdda5 100644 --- a/src/plugins/cpptools/cppmodelmanager.cpp +++ b/src/plugins/cpptools/cppmodelmanager.cpp @@ -752,7 +752,8 @@ QList CppModelManager::references(CPlusPlus::Symbol *symbol, CPlusPlus::Document::Ptr doc, const CPlusPlus::Snapshot &snapshot) { - return m_findReferences->references(LookupContext::canonicalSymbol(symbol), doc, snapshot); + NamespaceBindingPtr glo = bind(doc, snapshot); + return m_findReferences->references(LookupContext::canonicalSymbol(symbol, glo.data()), doc, snapshot); } void CppModelManager::findUsages(CPlusPlus::Symbol *symbol) -- GitLab