diff --git a/src/plugins/cppeditor/cppeditor.cpp b/src/plugins/cppeditor/cppeditor.cpp index b370faea1bb626a110c666102dbe4e4b7db9eda8..ab38af3772bcf99e78aa923f553987604f07aa88 100644 --- a/src/plugins/cppeditor/cppeditor.cpp +++ b/src/plugins/cppeditor/cppeditor.cpp @@ -45,6 +45,7 @@ #include <CoreTypes.h> #include <Literals.h> #include <Semantic.h> +#include <SymbolVisitor.h> #include <cplusplus/ExpressionUnderCursor.h> #include <cplusplus/LookupContext.h> #include <cplusplus/Overview.h> @@ -100,6 +101,44 @@ public: } }; +class FindFunctionDefinitions: protected SymbolVisitor +{ + Name *_declarationName; + QList<Function *> *_functions; + +public: + FindFunctionDefinitions() + : _declarationName(0), + _functions(0) + { } + + void operator()(Name *declarationName, Scope *globals, + QList<Function *> *functions) + { + _declarationName = declarationName; + _functions = functions; + + for (unsigned i = 0; i < globals->symbolCount(); ++i) { + accept(globals->symbolAt(i)); + } + } + +protected: + using SymbolVisitor::visit; + + virtual bool visit(Function *function) + { + Name *name = function->name(); + if (QualifiedNameId *q = name->asQualifiedNameId()) + name = q->unqualifiedNameId(); + + if (_declarationName->isEqualTo(name)) + _functions->append(function); + + return false; + } +}; + } // end of anonymous namespace QualifiedNameId *qualifiedNameIdForSymbol(Symbol *s, const LookupContext &context) @@ -550,58 +589,60 @@ void CPPEditor::jumpToDefinition() } } -Symbol *CPPEditor::findDefinition(Symbol *lastSymbol) +Symbol *CPPEditor::findDefinition(Symbol *symbol) { - // Currently only functions are supported - if (!lastSymbol->type()->isFunction()) - return 0; + if (symbol->isFunction()) + return 0; // symbol is a function definition. - QVector<Name *> qualifiedName; - Scope *scope = lastSymbol->scope(); - for (; scope; scope = scope->enclosingScope()) { - if (scope->isClassScope() || scope->isNamespaceScope()) { - if (scope->owner() && scope->owner()->name()) { - Name *scopeOwnerName = scope->owner()->name(); - if (QualifiedNameId *q = scopeOwnerName->asQualifiedNameId()) { - for (unsigned i = 0; i < q->nameCount(); ++i) { - qualifiedName.prepend(q->nameAt(i)); - } - } else { - qualifiedName.prepend(scopeOwnerName); - } - } + Function *funTy = symbol->type()->asFunction(); + if (! funTy) + return 0; // symbol does not have function type. + + Name *name = symbol->name(); + if (! name) + return 0; // skip anonymous functions! + + if (QualifiedNameId *q = name->asQualifiedNameId()) + name = q->unqualifiedNameId(); + + // map from file names to function definitions. + QMap<QString, QList<Function *> > functionDefinitions; + + // find function definitions. + FindFunctionDefinitions findFunctionDefinitions; + + // save the current snapshot + const Snapshot snapshot = m_modelManager->snapshot(); + + foreach (Document::Ptr doc, snapshot) { + if (Scope *globals = doc->globalSymbols()) { + QList<Function *> *localFunctionDefinitions = + &functionDefinitions[doc->fileName()]; + + findFunctionDefinitions(name, globals, + localFunctionDefinitions); } } - qualifiedName.append(lastSymbol->name()); - - Control control; - QualifiedNameId *q = control.qualifiedNameId(&qualifiedName[0], qualifiedName.size()); - LookupContext context(&control); - - const Snapshot documents = m_modelManager->snapshot(); - foreach (Document::Ptr doc, documents) { - QList<Scope *> visibleScopes; - visibleScopes.append(doc->globalSymbols()); - visibleScopes = context.expand(visibleScopes); - //qDebug() << "** doc:" << doc->fileName() << "visible scopes:" << visibleScopes.count(); - foreach (Scope *visibleScope, visibleScopes) { - Symbol *symbol = 0; - if (NameId *nameId = q->unqualifiedNameId()->asNameId()) - symbol = visibleScope->lookat(nameId->identifier()); - else if (DestructorNameId *dtorId = q->unqualifiedNameId()->asDestructorNameId()) - symbol = visibleScope->lookat(dtorId->identifier()); - else if (TemplateNameId *templNameId = q->unqualifiedNameId()->asTemplateNameId()) - symbol = visibleScope->lookat(templNameId->identifier()); - else if (OperatorNameId *opId = q->unqualifiedNameId()->asOperatorNameId()) - symbol = visibleScope->lookat(opId->kind()); - // ### cast operators - for (; symbol; symbol = symbol->next()) { - if (! symbol->isFunction()) - continue; - else if (! isCompatible(symbol->asFunction(), lastSymbol, q)) - continue; - return symbol; + // a dummy document. + Document::Ptr expressionDocument = Document::create("<empty>"); + + QMapIterator<QString, QList<Function *> > it(functionDefinitions); + while (it.hasNext()) { + it.next(); + + // get the instance of the document. + Document::Ptr thisDocument = snapshot.value(it.key()); + + foreach (Function *f, it.value()) { + // create a lookup context + const LookupContext context(f, expressionDocument, + thisDocument, snapshot); + + // search the matching definition for the function declaration `symbol'. + foreach (Symbol *s, context.resolve(f->name())) { + if (s == symbol) + return f; } } }