Commit 95a46450 authored by Roberto Raggi's avatar Roberto Raggi Committed by Thorbjørn Lindeijer
Browse files

Fixes: Improved lookup of function definitions.

parent 27c77134
...@@ -45,6 +45,7 @@ ...@@ -45,6 +45,7 @@
#include <CoreTypes.h> #include <CoreTypes.h>
#include <Literals.h> #include <Literals.h>
#include <Semantic.h> #include <Semantic.h>
#include <SymbolVisitor.h>
#include <cplusplus/ExpressionUnderCursor.h> #include <cplusplus/ExpressionUnderCursor.h>
#include <cplusplus/LookupContext.h> #include <cplusplus/LookupContext.h>
#include <cplusplus/Overview.h> #include <cplusplus/Overview.h>
...@@ -100,6 +101,44 @@ public: ...@@ -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 } // end of anonymous namespace
QualifiedNameId *qualifiedNameIdForSymbol(Symbol *s, const LookupContext &context) QualifiedNameId *qualifiedNameIdForSymbol(Symbol *s, const LookupContext &context)
...@@ -550,58 +589,60 @@ void CPPEditor::jumpToDefinition() ...@@ -550,58 +589,60 @@ void CPPEditor::jumpToDefinition()
} }
} }
Symbol *CPPEditor::findDefinition(Symbol *lastSymbol) Symbol *CPPEditor::findDefinition(Symbol *symbol)
{ {
// Currently only functions are supported if (symbol->isFunction())
if (!lastSymbol->type()->isFunction()) return 0; // symbol is a function definition.
return 0;
QVector<Name *> qualifiedName; Function *funTy = symbol->type()->asFunction();
Scope *scope = lastSymbol->scope(); if (! funTy)
for (; scope; scope = scope->enclosingScope()) { return 0; // symbol does not have function type.
if (scope->isClassScope() || scope->isNamespaceScope()) {
if (scope->owner() && scope->owner()->name()) { Name *name = symbol->name();
Name *scopeOwnerName = scope->owner()->name(); if (! name)
if (QualifiedNameId *q = scopeOwnerName->asQualifiedNameId()) { return 0; // skip anonymous functions!
for (unsigned i = 0; i < q->nameCount(); ++i) {
qualifiedName.prepend(q->nameAt(i)); if (QualifiedNameId *q = name->asQualifiedNameId())
} name = q->unqualifiedNameId();
} else {
qualifiedName.prepend(scopeOwnerName); // 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()); // a dummy document.
Document::Ptr expressionDocument = Document::create("<empty>");
Control control;
QualifiedNameId *q = control.qualifiedNameId(&qualifiedName[0], qualifiedName.size()); QMapIterator<QString, QList<Function *> > it(functionDefinitions);
LookupContext context(&control); while (it.hasNext()) {
it.next();
const Snapshot documents = m_modelManager->snapshot();
foreach (Document::Ptr doc, documents) { // get the instance of the document.
QList<Scope *> visibleScopes; Document::Ptr thisDocument = snapshot.value(it.key());
visibleScopes.append(doc->globalSymbols());
visibleScopes = context.expand(visibleScopes); foreach (Function *f, it.value()) {
//qDebug() << "** doc:" << doc->fileName() << "visible scopes:" << visibleScopes.count(); // create a lookup context
foreach (Scope *visibleScope, visibleScopes) { const LookupContext context(f, expressionDocument,
Symbol *symbol = 0; thisDocument, snapshot);
if (NameId *nameId = q->unqualifiedNameId()->asNameId())
symbol = visibleScope->lookat(nameId->identifier()); // search the matching definition for the function declaration `symbol'.
else if (DestructorNameId *dtorId = q->unqualifiedNameId()->asDestructorNameId()) foreach (Symbol *s, context.resolve(f->name())) {
symbol = visibleScope->lookat(dtorId->identifier()); if (s == symbol)
else if (TemplateNameId *templNameId = q->unqualifiedNameId()->asTemplateNameId()) return f;
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;
} }
} }
} }
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment