Commit 8848be4c authored by Roberto Raggi's avatar Roberto Raggi

Find references

parent f6104255
......@@ -203,7 +203,9 @@ ResolveExpression::ResolveExpression(const LookupContext &context)
: ASTVisitor(context.expressionDocument()->control()),
_context(context),
sem(_context.control())
{ }
{
_wantReferences = false;
}
ResolveExpression::~ResolveExpression()
{ }
......@@ -235,6 +237,7 @@ void ResolveExpression::addResult(const FullySpecifiedType &ty, Symbol *symbol)
void ResolveExpression::addResult(const Result &r)
{
Result p = r;
if (! p.second)
p.second = _context.symbol();
......
......@@ -47,6 +47,21 @@ public:
ResolveExpression(const LookupContext &context);
virtual ~ResolveExpression();
bool wantReferences() const
{ return _wantReferences; }
void setWantReferences(bool onoff)
{ _wantReferences = onoff; }
void setDeclSymbol(Symbol *symbol)
{
references.clear();
_wantReferences = true;
_declSymbol = symbol;
}
QList<unsigned> references;
QList<Result> operator()(ExpressionAST *ast);
QList<Result> resolveMemberExpression(const QList<Result> &baseResults,
......@@ -123,6 +138,8 @@ private:
LookupContext _context;
Semantic sem;
QList<Result> _results;
bool _wantReferences;
Symbol *_declSymbol;
};
class CPLUSPLUS_EXPORT ResolveClass
......
......@@ -32,6 +32,8 @@
#include "cppplugin.h"
#include "cpphighlighter.h"
#include <cpptools/cpptoolsplugin.h>
#include <AST.h>
#include <Control.h>
#include <Token.h>
......@@ -46,6 +48,7 @@
#include <SymbolVisitor.h>
#include <TranslationUnit.h>
#include <cplusplus/ExpressionUnderCursor.h>
#include <cplusplus/TypeOfExpression.h>
#include <cplusplus/LookupContext.h>
#include <cplusplus/Overview.h>
#include <cplusplus/OverviewModel.h>
......@@ -827,6 +830,51 @@ void CPPEditor::reformatDocument()
c.insertText(QString::fromUtf8(str.c_str(), str.length()));
}
void CPPEditor::findReferences()
{
QTextCursor tc = textCursor();
m_currentRenameSelection = -1;
int line, col;
convertPosition(tc.position(), &line, &col);
++col;
tc.movePosition(QTextCursor::EndOfWord);
ExpressionUnderCursor expressionUnderCursor;
const QString code = expressionUnderCursor(tc);
qDebug() << "code:" << code;
Snapshot snapshot = m_modelManager->snapshot();
Document::Ptr doc = snapshot.value(file()->fileName());
TypeOfExpression typeOfExpression;
typeOfExpression.setSnapshot(snapshot);
Symbol *lastVisibleSymbol = doc->findSymbolAt(line, col);
const QList<TypeOfExpression::Result> results = typeOfExpression(code, doc,
lastVisibleSymbol,
TypeOfExpression::Preprocess);
if (! results.isEmpty()) {
TypeOfExpression::Result result = results.first();
Symbol *symbol = result.second;
qDebug() << "result:" << symbol->fileName() << symbol->line() << symbol->column();
m_modelManager->findReferences(symbol);
}
#if 0
LookupContext context(
Overview oo;
qDebug() << "==============> filename:" << symbol->fileName()
<< "name:" << oo(symbol->name());
m_modelManager->findReferences(symbol);
}
#endif
}
void CPPEditor::renameSymbolUnderCursor()
{
updateSemanticInfo(m_semanticHighlighter->semanticInfo(currentSource()));
......
......@@ -197,6 +197,7 @@ public Q_SLOTS:
void switchDeclarationDefinition();
void jumpToDefinition();
void renameSymbolUnderCursor();
void findReferences();
void moveToPreviousToken();
void moveToNextToken();
......
......@@ -39,6 +39,7 @@ const char * const C_CPPEDITOR = "C++ Editor";
const char * const CPPEDITOR_KIND = QT_TRANSLATE_NOOP("OpenWith::Editors", "C++ Editor");
const char * const SWITCH_DECLARATION_DEFINITION = "CppEditor.SwitchDeclarationDefinition";
const char * const RENAME_SYMBOL_UNDER_CURSOR = "CppEditor.RenameSymbolUnderCursor";
const char * const FIND_REFERENCES = "CppEditor.FindReferences";
const char * const JUMP_TO_DEFINITION = "CppEditor.JumpToDefinition";
const char * const HEADER_FILE_TYPE = "CppHeaderFiles";
......
......@@ -220,6 +220,14 @@ bool CppPlugin::initialize(const QStringList & /*arguments*/, QString *errorMess
am->actionContainer(CppEditor::Constants::M_CONTEXT)->addAction(cmd);
am->actionContainer(CppTools::Constants::M_TOOLS_CPP)->addAction(cmd);
QAction *findReferencesAction = new QAction(tr("Find References"), this);
cmd = am->registerAction(findReferencesAction,
Constants::FIND_REFERENCES, context);
cmd->setDefaultKeySequence(QKeySequence("F3"));
connect(findReferencesAction, SIGNAL(triggered()), this, SLOT(findReferences()));
am->actionContainer(CppEditor::Constants::M_CONTEXT)->addAction(cmd);
am->actionContainer(CppTools::Constants::M_TOOLS_CPP)->addAction(cmd);
m_actionHandler = new TextEditor::TextEditorActionHandler(CppEditor::Constants::C_CPPEDITOR,
TextEditor::TextEditorActionHandler::Format
| TextEditor::TextEditorActionHandler::UnCommentSelection
......@@ -281,4 +289,12 @@ void CppPlugin::renameSymbolUnderCursor()
editor->renameSymbolUnderCursor();
}
void CppPlugin::findReferences()
{
Core::EditorManager *em = Core::EditorManager::instance();
CPPEditor *editor = qobject_cast<CPPEditor*>(em->currentEditor()->widget());
if (editor)
editor->findReferences();
}
Q_EXPORT_PLUGIN(CppPlugin)
......@@ -74,6 +74,7 @@ private slots:
void switchDeclarationDefinition();
void jumpToDefinition();
void renameSymbolUnderCursor();
void findReferences();
private:
Core::IEditor *createEditor(QWidget *parent);
......
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** GNU Lesser General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at http://www.qtsoftware.com/contact.
**
**************************************************************************/
#include "cppfindreferences.h"
#include "cppmodelmanager.h"
#include "cpptoolsconstants.h"
#include <texteditor/basetexteditor.h>
#include <find/searchresultwindow.h>
#include <extensionsystem/pluginmanager.h>
#include <utils/filesearch.h>
#include <coreplugin/progressmanager/progressmanager.h>
#include <coreplugin/icore.h>
#include <ASTVisitor.h>
#include <AST.h>
#include <Control.h>
#include <Literals.h>
#include <TranslationUnit.h>
#include <Symbols.h>
#include <cplusplus/CppDocument.h>
#include <cplusplus/ExpressionUnderCursor.h>
#include <cplusplus/ResolveExpression.h>
#include <QtCore/QTime>
#include <QtCore/QtConcurrentRun>
#include <QtCore/QDir>
#include <qtconcurrent/runextensions.h>
using namespace CppTools::Internal;
using namespace CPlusPlus;
namespace {
struct Process: protected ASTVisitor
{
public:
Process(QFutureInterface<Core::Utils::FileSearchResult> &future,
Document::Ptr doc, const Snapshot &snapshot)
: ASTVisitor(doc->control()),
_future(future),
_doc(doc),
_snapshot(snapshot),
_source(_doc->source())
{ }
void operator()(Identifier *id, AST *ast)
{
_id = id;
_currentSymbol = _doc->globalNamespace();
_exprDoc = Document::create("<references>");
accept(ast);
}
protected:
using ASTVisitor::visit;
QString matchingLine(const Token &tk) const
{
const char *beg = _source.constData();
const char *cp = beg + tk.offset;
for (; cp != beg - 1; --cp) {
if (*cp == '\n')
break;
}
++cp;
const char *lineEnd = cp + 1;
for (; *lineEnd; ++lineEnd) {
if (*lineEnd == '\n')
break;
}
const QString matchingLine = QString::fromUtf8(cp, lineEnd - cp);
return matchingLine;
}
void reportResult(unsigned tokenIndex)
{
const Token &tk = tokenAt(tokenIndex);
const QString lineText = matchingLine(tk);
unsigned line, col;
getTokenStartPosition(tokenIndex, &line, &col);
if (col)
--col; // adjust the column position.
int len = tk.f.length;
_future.reportResult(Core::Utils::FileSearchResult(QDir::toNativeSeparators(_doc->fileName()),
line, lineText, col, len));
}
LookupContext currentContext() const
{
return LookupContext(_currentSymbol, _exprDoc, _doc, _snapshot);
}
virtual bool visit(ClassSpecifierAST *ast)
{
_currentSymbol = ast->symbol;
return true;
}
virtual bool visit(NamespaceAST *ast)
{
_currentSymbol = ast->symbol;
return true;
}
virtual bool visit(CompoundStatementAST *ast)
{
_currentSymbol = ast->symbol;
return true;
}
virtual bool visit(FunctionDefinitionAST *ast)
{
_currentSymbol = ast->symbol;
return true;
}
virtual bool visit(QualifiedNameAST *ast)
{
return true;
}
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);
}
return false;
}
virtual bool visit(TemplateIdAST *ast)
{
Identifier *id = identifier(ast->identifier_token);
if (id == _id)
reportResult(ast->identifier_token);
return true;
}
private:
QFutureInterface<Core::Utils::FileSearchResult> &_future;
Identifier *_id;
Document::Ptr _doc;
Snapshot _snapshot;
QByteArray _source;
Symbol *_currentSymbol;
Document::Ptr _exprDoc;
};
} // end of anonymous namespace
CppFindReferences::CppFindReferences(CppModelManager *modelManager)
: _modelManager(modelManager),
_resultWindow(ExtensionSystem::PluginManager::instance()->getObject<Find::SearchResultWindow>())
{
m_watcher.setPendingResultsLimit(1);
connect(&m_watcher, SIGNAL(resultReadyAt(int)), this, SLOT(displayResult(int)));
connect(&m_watcher, SIGNAL(finished()), this, SLOT(searchFinished()));
}
CppFindReferences::~CppFindReferences()
{
}
static void find_helper(QFutureInterface<Core::Utils::FileSearchResult> &future,
QString word,
QString fileName,
Snapshot snapshot)
{
QTime tm;
tm.start();
QStringList files(fileName);
files += snapshot.dependsOn(fileName);
qDebug() << "done in:" << tm.elapsed() << "number of files to parse:" << files.size();
future.setProgressRange(0, files.size());
tm.start();
for (int i = 0; i < files.size(); ++i) {
const QString &fn = files.at(i);
future.setProgressValueAndText(i, QFileInfo(fn).fileName());
QFile f(fn);
if (! f.open(QFile::ReadOnly))
continue;
const QString source = QTextStream(&f).readAll();
const QByteArray preprocessedCode = snapshot.preprocessedCode(source, fn);
Document::Ptr doc = snapshot.documentFromSource(preprocessedCode, fn);
doc->check();
Control *control = doc->control();
Identifier *id = control->findOrInsertIdentifier(word.toLatin1().constData());
TranslationUnit *unit = doc->translationUnit();
Process process(future, doc, snapshot);
process(id, unit->ast());
}
future.setProgressValue(files.size());
}
void CppFindReferences::findAll(const QString &fileName, const QString &text)
{
_resultWindow->clearContents();
_resultWindow->popup(true);
Core::ProgressManager *progressManager = Core::ICore::instance()->progressManager();
const Snapshot snapshot = _modelManager->snapshot();
QFuture<Core::Utils::FileSearchResult> result =
QtConcurrent::run(&find_helper, text, fileName, snapshot);
m_watcher.setFuture(result);
Core::FutureProgress *progress = progressManager->addTask(result, tr("Searching..."),
CppTools::Constants::TASK_INDEX,
Core::ProgressManager::CloseOnSuccess);
connect(progress, SIGNAL(clicked()), _resultWindow, SLOT(popup()));
}
void CppFindReferences::displayResult(int index)
{
Core::Utils::FileSearchResult result = m_watcher.future().resultAt(index);
Find::ResultWindowItem *item = _resultWindow->addResult(result.fileName,
result.lineNumber,
result.matchingLine,
result.matchStart,
result.matchLength);
if (item)
connect(item, SIGNAL(activated(const QString&,int,int)),
this, SLOT(openEditor(const QString&,int,int)));
}
void CppFindReferences::searchFinished()
{
emit changed();
}
void CppFindReferences::openEditor(const QString &fileName, int line, int column)
{
TextEditor::BaseTextEditor::openEditorAt(fileName, line, column);
}
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** GNU Lesser General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at http://www.qtsoftware.com/contact.
**
**************************************************************************/
#ifndef CPPFINDREFERENCES_H
#define CPPFINDREFERENCES_H
#include <QtCore/QObject>
#include <QtCore/QPointer>
#include <QtCore/QFuture>
#include <QtCore/QFutureWatcher>
namespace Core {
namespace Utils {
class FileSearchResult;
} // end of namespace Utils
} // end of namespace Core
namespace Find {
class SearchResultWindow;
} // end of namespace Find
namespace CppTools {
namespace Internal {
class CppModelManager;
class CppFindReferences: public QObject
{
Q_OBJECT
public:
CppFindReferences(CppModelManager *modelManager);
virtual ~CppFindReferences();
Q_SIGNALS:
void changed();
public:
void findAll(const QString &fileName, const QString &text);
private Q_SLOTS:
void displayResult(int);
void searchFinished();
void openEditor(const QString&, int, int);
private:
QPointer<CppModelManager> _modelManager;
Find::SearchResultWindow *_resultWindow;
QFutureWatcher<Core::Utils::FileSearchResult> m_watcher;
};
} // end of namespace Internal
} // end of namespace CppTools
#endif // CPPFINDREFERENCES_H
......@@ -35,6 +35,7 @@
#include "cppmodelmanager.h"
#include "cpptoolsconstants.h"
#include "cpptoolseditorsupport.h"
#include "cppfindreferences.h"
#include <functional>
#include <QtConcurrentRun>
......@@ -579,6 +580,8 @@ Document::Ptr CppPreprocessor::switchDocument(Document::Ptr doc)
CppModelManager::CppModelManager(QObject *parent)
: CppModelManagerInterface(parent)
{
m_findReferences = new CppFindReferences(this);
m_revision = 0;
m_synchronizer.setCancelOnWait(true);
......@@ -715,6 +718,14 @@ void CppModelManager::removeEditorSupport(AbstractEditorSupport *editorSupport)
m_addtionalEditorSupport.remove(editorSupport);
}
void CppModelManager::findReferences(CPlusPlus::Symbol *symbol)
{
if (Identifier *id = symbol->identifier()) {
QString word = QString::fromLatin1(id->chars(), id->size());
m_findReferences->findAll(symbol->fileName(), word);
}
}
QMap<QString, QString> CppModelManager::buildWorkingCopyList()
{
QMap<QString, QString> workingCopy;
......
......@@ -62,6 +62,7 @@ namespace Internal {
class CppEditorSupport;
class CppPreprocessor;
class CppFindReferences;
class CppModelManager : public CppModelManagerInterface
{
......@@ -101,6 +102,8 @@ public:
virtual void addEditorSupport(AbstractEditorSupport *editorSupport);
virtual void removeEditorSupport(AbstractEditorSupport *editorSupport);
virtual void findReferences(CPlusPlus::Symbol *symbol);
void setHeaderSuffixes(const QStringList &suffixes)
{ m_headerSuffixes = suffixes; }
......@@ -205,6 +208,8 @@ private:
QFutureSynchronizer<void> m_synchronizer;
unsigned m_revision;
CppFindReferences *m_findReferences;
};
} // namespace Internal
......
......@@ -94,6 +94,8 @@ public:
virtual void addEditorSupport(AbstractEditorSupport *editorSupport) = 0;
virtual void removeEditorSupport(AbstractEditorSupport *editorSupport) = 0;
virtual void findReferences(CPlusPlus::Symbol *symbol) = 0;
};
class CPPTOOLS_EXPORT AbstractEditorSupport
......
......@@ -23,7 +23,8 @@ HEADERS += completionsettingspage.h \
searchsymbols.h \
cppdoxygen.h \
cppfilesettingspage.h \
cppsemanticsearch.h
cppsemanticsearch.h \
cppfindreferences.h
SOURCES += completionsettingspage.cpp \
cppclassesfilter.cpp \
......@@ -38,7 +39,8 @@ SOURCES += completionsettingspage.cpp \
cppdoxygen.cpp \
cppfilesettingspage.cpp \
abstracteditorsupport.cpp \
cppsemanticsearch.cpp
cppsemanticsearch.cpp \
cppfindreferences.cpp
FORMS += completionsettingspage.ui \
cppfilesettingspage.ui
......
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