forked from qt-creator/qt-creator
Some work on `find references of a symbol'.
This commit is contained in:
@@ -44,10 +44,13 @@
|
||||
#include <Literals.h>
|
||||
#include <TranslationUnit.h>
|
||||
#include <Symbols.h>
|
||||
#include <Names.h>
|
||||
#include <Scope.h>
|
||||
|
||||
#include <cplusplus/CppDocument.h>
|
||||
#include <cplusplus/ExpressionUnderCursor.h>
|
||||
#include <cplusplus/ResolveExpression.h>
|
||||
#include <cplusplus/Overview.h>
|
||||
|
||||
#include <QtCore/QTime>
|
||||
#include <QtCore/QtConcurrentRun>
|
||||
@@ -69,13 +72,16 @@ public:
|
||||
_future(future),
|
||||
_doc(doc),
|
||||
_snapshot(snapshot),
|
||||
_source(_doc->source())
|
||||
{ }
|
||||
|
||||
void operator()(Identifier *id, AST *ast)
|
||||
_source(_doc->source()),
|
||||
_sem(doc->control())
|
||||
{
|
||||
_snapshot.insert(_doc);
|
||||
}
|
||||
|
||||
void operator()(Symbol *symbol, Identifier *id, AST *ast)
|
||||
{
|
||||
_declSymbol = symbol;
|
||||
_id = id;
|
||||
_currentSymbol = _doc->globalNamespace();
|
||||
_exprDoc = Document::create("<references>");
|
||||
accept(ast);
|
||||
}
|
||||
@@ -122,55 +128,63 @@ protected:
|
||||
line, lineText, col, len));
|
||||
}
|
||||
|
||||
LookupContext currentContext() const
|
||||
bool checkCandidates(const QList<Symbol *> &candidates) const
|
||||
{
|
||||
return LookupContext(_currentSymbol, _exprDoc, _doc, _snapshot);
|
||||
}
|
||||
|
||||
virtual bool visit(ClassSpecifierAST *ast)
|
||||
{
|
||||
_currentSymbol = ast->symbol;
|
||||
// ### FIXME return isDeclSymbol(LookupContext::canonicalSymbol(candidates));
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual bool visit(NamespaceAST *ast)
|
||||
bool isDeclSymbol(Symbol *symbol) const
|
||||
{
|
||||
_currentSymbol = ast->symbol;
|
||||
return true;
|
||||
if (! symbol)
|
||||
return false;
|
||||
|
||||
else if (symbol == _declSymbol)
|
||||
return true;
|
||||
|
||||
else if (symbol->line() == _declSymbol->line() && symbol->column() == _declSymbol->column()) {
|
||||
if (! qstrcmp(symbol->fileName(), _declSymbol->fileName()))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual bool visit(CompoundStatementAST *ast)
|
||||
LookupContext currentContext(AST *ast) const
|
||||
{
|
||||
_currentSymbol = ast->symbol;
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual bool visit(FunctionDefinitionAST *ast)
|
||||
{
|
||||
_currentSymbol = ast->symbol;
|
||||
return true;
|
||||
unsigned line, column;
|
||||
getTokenStartPosition(ast->firstToken(), &line, &column);
|
||||
Symbol *lastVisibleSymbol = _doc->findSymbolAt(line, column);
|
||||
return LookupContext(lastVisibleSymbol, _exprDoc, _doc, _snapshot);
|
||||
}
|
||||
|
||||
virtual bool visit(QualifiedNameAST *ast)
|
||||
{
|
||||
return true;
|
||||
if (! ast->name) {
|
||||
//qWarning() << "invalid AST at" << _doc->fileName() << line << column;
|
||||
ast->name = _sem.check(ast, /*scope */ static_cast<Scope *>(0));
|
||||
}
|
||||
|
||||
Q_ASSERT(ast->name != 0);
|
||||
Identifier *id = ast->name->identifier();
|
||||
if (id == _id && ast->unqualified_name) {
|
||||
LookupContext context = currentContext(ast);
|
||||
const QList<Symbol *> candidates = context.resolve(ast->name);
|
||||
if (checkCandidates(candidates))
|
||||
reportResult(ast->unqualified_name->firstToken());
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual bool visit(SimpleNameAST *ast)
|
||||
{
|
||||
Identifier *id = identifier(ast->identifier_token);
|
||||
if (id == _id) {
|
||||
#if 0
|
||||
LookupContext context = currentContext();
|
||||
ResolveExpression resolveExpression(context);
|
||||
QList<ResolveExpression::Result> results = resolveExpression(ast);
|
||||
if (! results.isEmpty()) {
|
||||
ResolveExpression::Result result = results.first();
|
||||
Symbol *resolvedSymbol = result.second;
|
||||
qDebug() << "resolves to:" << resolvedSymbol->fileName() << resolvedSymbol->line();
|
||||
}
|
||||
#endif
|
||||
reportResult(ast->identifier_token);
|
||||
LookupContext context = currentContext(ast);
|
||||
const QList<Symbol *> candidates = context.resolve(ast->name);
|
||||
if (checkCandidates(candidates))
|
||||
reportResult(ast->identifier_token);
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -179,20 +193,25 @@ protected:
|
||||
virtual bool visit(TemplateIdAST *ast)
|
||||
{
|
||||
Identifier *id = identifier(ast->identifier_token);
|
||||
if (id == _id)
|
||||
reportResult(ast->identifier_token);
|
||||
if (id == _id) {
|
||||
LookupContext context = currentContext(ast);
|
||||
const QList<Symbol *> candidates = context.resolve(ast->name);
|
||||
if (checkCandidates(candidates))
|
||||
reportResult(ast->identifier_token);
|
||||
}
|
||||
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
private:
|
||||
QFutureInterface<Core::Utils::FileSearchResult> &_future;
|
||||
Identifier *_id;
|
||||
Identifier *_id; // ### remove me
|
||||
Symbol *_declSymbol;
|
||||
Document::Ptr _doc;
|
||||
Snapshot _snapshot;
|
||||
QByteArray _source;
|
||||
Symbol *_currentSymbol;
|
||||
Document::Ptr _exprDoc;
|
||||
Semantic _sem;
|
||||
};
|
||||
|
||||
} // end of anonymous namespace
|
||||
@@ -217,6 +236,9 @@ static void find_helper(QFutureInterface<Core::Utils::FileSearchResult> &future,
|
||||
QTime tm;
|
||||
tm.start();
|
||||
|
||||
Identifier *symbolId = symbol->identifier();
|
||||
Q_ASSERT(symbolId != 0);
|
||||
|
||||
const QString fileName = QString::fromUtf8(symbol->fileName(), symbol->fileNameLength());
|
||||
|
||||
QStringList files(fileName);
|
||||
@@ -229,24 +251,30 @@ static void find_helper(QFutureInterface<Core::Utils::FileSearchResult> &future,
|
||||
for (int i = 0; i < files.size(); ++i) {
|
||||
const QString &fn = files.at(i);
|
||||
future.setProgressValueAndText(i, QFileInfo(fn).fileName());
|
||||
|
||||
Document::Ptr previousDoc = snapshot.value(fn);
|
||||
if (previousDoc) {
|
||||
Control *control = previousDoc->control();
|
||||
Identifier *id = control->findIdentifier(symbolId->chars(), symbolId->size());
|
||||
if (! id)
|
||||
continue; // skip this document, it's not using symbolId.
|
||||
}
|
||||
|
||||
QFile f(fn);
|
||||
if (! f.open(QFile::ReadOnly))
|
||||
continue;
|
||||
|
||||
const QString source = QTextStream(&f).readAll();
|
||||
const QString source = QTextStream(&f).readAll(); // ### FIXME
|
||||
const QByteArray preprocessedCode = snapshot.preprocessedCode(source, fn);
|
||||
Document::Ptr doc = snapshot.documentFromSource(preprocessedCode, fn);
|
||||
doc->tokenize();
|
||||
|
||||
Identifier *symbolId = symbol->identifier();
|
||||
Q_ASSERT(symbolId != 0);
|
||||
|
||||
Control *control = doc->control();
|
||||
if (Identifier *id = control->findIdentifier(symbolId->chars(), symbolId->size())) {
|
||||
doc->check();
|
||||
TranslationUnit *unit = doc->translationUnit();
|
||||
Process process(future, doc, snapshot);
|
||||
process(id, unit->ast());
|
||||
process(symbol, id, unit->ast());
|
||||
}
|
||||
}
|
||||
future.setProgressValue(files.size());
|
||||
@@ -259,16 +287,7 @@ void CppFindReferences::findAll(const Snapshot &snapshot, Symbol *symbol)
|
||||
|
||||
Core::ProgressManager *progressManager = Core::ICore::instance()->progressManager();
|
||||
|
||||
// find the canonical symbol.
|
||||
Symbol *canonicalSymbol = symbol;
|
||||
for (; symbol; symbol = symbol->next()) {
|
||||
if (symbol->name() == canonicalSymbol->name())
|
||||
canonicalSymbol = symbol;
|
||||
}
|
||||
|
||||
QFuture<Core::Utils::FileSearchResult> result =
|
||||
QtConcurrent::run(&find_helper, snapshot, canonicalSymbol);
|
||||
|
||||
QFuture<Core::Utils::FileSearchResult> result = QtConcurrent::run(&find_helper, snapshot, symbol);
|
||||
m_watcher.setFuture(result);
|
||||
|
||||
Core::FutureProgress *progress = progressManager->addTask(result, tr("Searching..."),
|
||||
|
||||
Reference in New Issue
Block a user