forked from qt-creator/qt-creator
Fixes: Improved lookup of function definitions.
This commit is contained in:
committed by
Thorbjørn Lindeijer
parent
27c771343e
commit
95a4645029
@@ -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:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
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()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
QMapIterator<QString, QList<Function *> > it(functionDefinitions);
|
||||||
QualifiedNameId *q = control.qualifiedNameId(&qualifiedName[0], qualifiedName.size());
|
while (it.hasNext()) {
|
||||||
LookupContext context(&control);
|
it.next();
|
||||||
|
|
||||||
const Snapshot documents = m_modelManager->snapshot();
|
// get the instance of the document.
|
||||||
foreach (Document::Ptr doc, documents) {
|
Document::Ptr thisDocument = snapshot.value(it.key());
|
||||||
QList<Scope *> visibleScopes;
|
|
||||||
visibleScopes.append(doc->globalSymbols());
|
foreach (Function *f, it.value()) {
|
||||||
visibleScopes = context.expand(visibleScopes);
|
// create a lookup context
|
||||||
//qDebug() << "** doc:" << doc->fileName() << "visible scopes:" << visibleScopes.count();
|
const LookupContext context(f, expressionDocument,
|
||||||
foreach (Scope *visibleScope, visibleScopes) {
|
thisDocument, snapshot);
|
||||||
Symbol *symbol = 0;
|
|
||||||
if (NameId *nameId = q->unqualifiedNameId()->asNameId())
|
// search the matching definition for the function declaration `symbol'.
|
||||||
symbol = visibleScope->lookat(nameId->identifier());
|
foreach (Symbol *s, context.resolve(f->name())) {
|
||||||
else if (DestructorNameId *dtorId = q->unqualifiedNameId()->asDestructorNameId())
|
if (s == symbol)
|
||||||
symbol = visibleScope->lookat(dtorId->identifier());
|
return f;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user