Commit 271fb797 authored by Erik Verbruggen's avatar Erik Verbruggen

Made symbol searching plug-able through indexing support.

The indexing support for the built-in code model is moved to its own
file. Symbol searching will now call for a searcher through that support
interface, which will create a fully configured and ready-to-go searcher
that can be started in the/a future.

Change-Id: Idc3ee1c7c789a69fa05ee1d42415313dcea94cf8
Reviewed-by: default avatarNikolai Kosjar <nikolai.kosjar@digia.com>
parent 65942d2d
......@@ -221,7 +221,8 @@ public:
virtual CppTools::CppHighlightingSupport *highlightingSupport(Core::IEditor *editor) const = 0;
virtual void setHighlightingSupportFactory(CppTools::CppHighlightingSupportFactory *highlightingFactory) = 0;
virtual void addIndexingSupport(CppTools::CppIndexingSupport *indexingSupport) = 0;
virtual void setIndexingSupport(CppTools::CppIndexingSupport *indexingSupport) = 0;
virtual CppTools::CppIndexingSupport *indexingSupport() = 0;
Q_SIGNALS:
void documentUpdated(CPlusPlus::Document::Ptr doc);
......
#include "builtinindexingsupport.h"
#include "cppmodelmanager.h"
#include "searchsymbols.h"
#include <coreplugin/icore.h>
#include <coreplugin/mimedatabase.h>
#include <coreplugin/progressmanager/progressmanager.h>
#include <utils/runextensions.h>
#include <QCoreApplication>
using namespace CppTools;
using namespace CppTools::Internal;
namespace {
static void parse(QFutureInterface<void> &future,
CppPreprocessor *preproc,
QStringList files,
const char *pp_configuration_file)
{
if (files.isEmpty())
return;
const Core::MimeDatabase *mimeDb = Core::ICore::mimeDatabase();
Core::MimeType cSourceTy = mimeDb->findByType(QLatin1String("text/x-csrc"));
Core::MimeType cppSourceTy = mimeDb->findByType(QLatin1String("text/x-c++src"));
Core::MimeType mSourceTy = mimeDb->findByType(QLatin1String("text/x-objcsrc"));
QStringList sources;
QStringList headers;
QStringList suffixes = cSourceTy.suffixes();
suffixes += cppSourceTy.suffixes();
suffixes += mSourceTy.suffixes();
foreach (const QString &file, files) {
QFileInfo info(file);
preproc->snapshot.remove(file);
if (suffixes.contains(info.suffix()))
sources.append(file);
else
headers.append(file);
}
const int sourceCount = sources.size();
files = sources;
files += headers;
preproc->setTodo(files);
future.setProgressRange(0, files.size());
QString conf = QLatin1String(pp_configuration_file);
bool processingHeaders = false;
for (int i = 0; i < files.size(); ++i) {
if (future.isPaused())
future.waitForResume();
if (future.isCanceled())
break;
const QString fileName = files.at(i);
const bool isSourceFile = i < sourceCount;
if (isSourceFile)
(void) preproc->run(conf);
else if (! processingHeaders) {
(void) preproc->run(conf);
processingHeaders = true;
}
preproc->run(fileName);
future.setProgressValue(files.size() - preproc->todo().size());
if (isSourceFile)
preproc->resetEnvironment();
}
future.setProgressValue(files.size());
preproc->modelManager()->finishedRefreshingSourceFiles(files);
delete preproc;
}
class BuiltinSymbolSearcher: public SymbolSearcher
{
public:
BuiltinSymbolSearcher(const CPlusPlus::Snapshot &snapshot,
Parameters parameters, QSet<QString> fileNames)
: m_snapshot(snapshot)
, m_parameters(parameters)
, m_fileNames(fileNames)
{}
~BuiltinSymbolSearcher()
{}
void runSearch(QFutureInterface<Find::SearchResultItem> &future)
{
future.setProgressRange(0, m_snapshot.size());
future.setProgressValue(0);
int progress = 0;
SearchSymbols search;
search.setSymbolsToSearchFor(m_parameters.types);
search.setSeparateScope(true);
CPlusPlus::Snapshot::const_iterator it = m_snapshot.begin();
QString findString = (m_parameters.flags & Find::FindRegularExpression
? m_parameters.text : QRegExp::escape(m_parameters.text));
if (m_parameters.flags & Find::FindWholeWords)
findString = QString::fromLatin1("\\b%1\\b").arg(findString);
QRegExp matcher(findString, (m_parameters.flags & Find::FindCaseSensitively
? Qt::CaseSensitive : Qt::CaseInsensitive));
while (it != m_snapshot.end()) {
if (future.isPaused())
future.waitForResume();
if (future.isCanceled())
break;
if (m_fileNames.isEmpty() || m_fileNames.contains(it.value()->fileName())) {
QVector<Find::SearchResultItem> resultItems;
QList<ModelItemInfo> modelInfos = search(it.value());
foreach (const ModelItemInfo &info, modelInfos) {
int index = matcher.indexIn(info.symbolName);
if (index != -1) {
QStringList path = info.fullyQualifiedName.mid(0,
info.fullyQualifiedName.size() - 1);
Find::SearchResultItem item;
item.path = path;
item.text = info.symbolName;
item.textMarkPos = -1;
item.textMarkLength = 0;
item.icon = info.icon;
item.lineNumber = -1;
item.userData = qVariantFromValue(info);
resultItems << item;
}
}
if (!resultItems.isEmpty())
future.reportResults(resultItems);
}
++it;
++progress;
future.setProgressValue(progress);
}
if (future.isPaused())
future.waitForResume();
}
private:
const CPlusPlus::Snapshot m_snapshot;
const Parameters m_parameters;
const QSet<QString> m_fileNames;
};
} // anonymous namespace
BuiltinIndexingSupport::BuiltinIndexingSupport(const char *pp_configuration_file)
: m_pp_configuration_file(pp_configuration_file)
, m_revision(0)
{
m_synchronizer.setCancelOnWait(true);
m_dumpFileNameWhileParsing = !qgetenv("QTCREATOR_DUMP_FILENAME_WHILE_PARSING").isNull();
}
BuiltinIndexingSupport::~BuiltinIndexingSupport()
{}
QFuture<void> BuiltinIndexingSupport::refreshSourceFiles(const QStringList &sourceFiles)
{
CppModelManager *mgr = CppModelManager::instance();
const WorkingCopy workingCopy = mgr->workingCopy();
CppPreprocessor *preproc = new CppPreprocessor(mgr, m_dumpFileNameWhileParsing);
preproc->setRevision(++m_revision);
preproc->setProjectFiles(mgr->projectFiles());
preproc->setIncludePaths(mgr->includePaths());
preproc->setFrameworkPaths(mgr->frameworkPaths());
preproc->setWorkingCopy(workingCopy);
QFuture<void> result = QtConcurrent::run(&parse, preproc, sourceFiles, m_pp_configuration_file);
if (m_synchronizer.futures().size() > 10) {
QList<QFuture<void> > futures = m_synchronizer.futures();
m_synchronizer.clearFutures();
foreach (const QFuture<void> &future, futures) {
if (! (future.isFinished() || future.isCanceled()))
m_synchronizer.addFuture(future);
}
}
m_synchronizer.addFuture(result);
if (sourceFiles.count() > 1) {
Core::ICore::progressManager()->addTask(result,
QCoreApplication::translate("IndexingSupport", "Parsing"),
QLatin1String(CppTools::Constants::TASK_INDEX));
}
return result;
}
SymbolSearcher *BuiltinIndexingSupport::createSymbolSearcher(SymbolSearcher::Parameters parameters, QSet<QString> fileNames)
{
return new BuiltinSymbolSearcher(CppModelManager::instance()->snapshot(), parameters, fileNames);
}
#ifndef BUILTININDEXINGSUPPORT_H
#define BUILTININDEXINGSUPPORT_H
#include "cppindexingsupport.h"
#include "ModelManagerInterface.h"
#include <QFutureSynchronizer>
namespace CppTools {
namespace Internal {
class BuiltinIndexingSupport: public CppIndexingSupport {
public:
typedef CPlusPlus::CppModelManagerInterface::WorkingCopy WorkingCopy;
public:
BuiltinIndexingSupport(const char *m_pp_configuration_file);
~BuiltinIndexingSupport();
virtual QFuture<void> refreshSourceFiles(const QStringList &sourceFiles);
virtual SymbolSearcher *createSymbolSearcher(SymbolSearcher::Parameters parameters, QSet<QString> fileNames);
private:
const char *m_pp_configuration_file;
QFutureSynchronizer<void> m_synchronizer;
unsigned m_revision;
bool m_dumpFileNameWhileParsing;
};
} // namespace Internal
} // namespace CppTools
#endif // BUILTININDEXINGSUPPORT_H
......@@ -38,7 +38,7 @@ CppClassesFilter::CppClassesFilter(CppModelManager *manager)
setShortcutString(QLatin1String("c"));
setIncludedByDefault(false);
search.setSymbolsToSearchFor(SearchSymbols::Classes);
search.setSymbolsToSearchFor(SymbolSearcher::Classes);
search.setSeparateScope(true);
}
......
......@@ -43,10 +43,10 @@ CppCurrentDocumentFilter::CppCurrentDocumentFilter(CppModelManager *manager, Cor
setShortcutString(QString(QLatin1Char('.')));
setIncludedByDefault(false);
search.setSymbolsToSearchFor(SearchSymbols::Declarations |
SearchSymbols::Enums |
SearchSymbols::Functions |
SearchSymbols::Classes);
search.setSymbolsToSearchFor(SymbolSearcher::Declarations |
SymbolSearcher::Enums |
SymbolSearcher::Functions |
SymbolSearcher::Classes);
search.setSeparateScope(true);
......
......@@ -37,7 +37,7 @@ CppFunctionsFilter::CppFunctionsFilter(CppModelManager *manager)
setShortcutString(QString(QLatin1Char('m')));
setIncludedByDefault(false);
search.setSymbolsToSearchFor(SearchSymbols::Functions);
search.setSymbolsToSearchFor(SymbolSearcher::Functions);
search.setSeparateScope(true);
}
......
......@@ -36,4 +36,12 @@ CppIndexingSupport::~CppIndexingSupport()
{
}
SymbolSearcher::SymbolSearcher(QObject *parent)
: QObject(parent)
{
}
SymbolSearcher::~SymbolSearcher()
{}
} // namespace CppTools
......@@ -32,19 +32,62 @@
#include "cpptools_global.h"
#include <find/searchresultwindow.h>
#include <find/textfindconstants.h>
#include <QFuture>
#include <QStringList>
namespace CppTools {
class SymbolSearcher: public QObject
{
Q_OBJECT
public:
enum SymbolType {
Classes = 0x1,
Functions = 0x2,
Enums = 0x4,
Declarations = 0x8
};
Q_DECLARE_FLAGS(SymbolTypes, SymbolType)
enum SearchScope {
SearchProjectsOnly,
SearchGlobal
};
struct Parameters
{
QString text;
Find::FindFlags flags;
SymbolTypes types;
SearchScope scope;
};
public:
SymbolSearcher(QObject *parent = 0);
virtual ~SymbolSearcher() = 0;
virtual void runSearch(QFutureInterface<Find::SearchResultItem> &future) = 0;
};
class CPPTOOLS_EXPORT CppIndexingSupport
{
public:
virtual ~CppIndexingSupport() = 0;
virtual QFuture<void> refreshSourceFiles(const QStringList &sourceFiles) = 0;
virtual SymbolSearcher *createSymbolSearcher(SymbolSearcher::Parameters parameters, QSet<QString> fileNames) = 0;
};
} // namespace CppTools
Q_DECLARE_METATYPE(CppTools::SymbolSearcher::SearchScope)
Q_DECLARE_METATYPE(CppTools::SymbolSearcher::Parameters)
Q_DECLARE_METATYPE(CppTools::SymbolSearcher::SymbolTypes)
#endif // CPPTOOLS_CPPINDEXINGSUPPORT_H
......@@ -30,6 +30,7 @@
#include <cplusplus/pp.h>
#include <cplusplus/Overview.h>
#include "builtinindexingsupport.h"
#include "cppmodelmanager.h"
#include "cppcompletionassist.h"
#include "cpphighlightingsupport.h"
......@@ -662,144 +663,6 @@ void CppModelManager::updateModifiedSourceFiles()
updateSourceFiles(sourceFiles);
}
namespace {
class IndexingSupport: public CppIndexingSupport {
public:
typedef CppModelManagerInterface::WorkingCopy WorkingCopy;
public:
IndexingSupport()
: m_revision(0)
{
m_synchronizer.setCancelOnWait(true);
m_dumpFileNameWhileParsing = !qgetenv("QTCREATOR_DUMP_FILENAME_WHILE_PARSING").isNull();
}
~IndexingSupport()
{}
QFuture<void> refreshSourceFiles(const QStringList &sourceFiles)
{
CppModelManager *mgr = CppModelManager::instance();
const WorkingCopy workingCopy = mgr->workingCopy();
CppPreprocessor *preproc = new CppPreprocessor(mgr, m_dumpFileNameWhileParsing);
preproc->setRevision(++m_revision);
preproc->setProjectFiles(mgr->projectFiles());
preproc->setIncludePaths(mgr->includePaths());
preproc->setFrameworkPaths(mgr->frameworkPaths());
preproc->setWorkingCopy(workingCopy);
QFuture<void> result = QtConcurrent::run(&parse, preproc, sourceFiles);
if (m_synchronizer.futures().size() > 10) {
QList<QFuture<void> > futures = m_synchronizer.futures();
m_synchronizer.clearFutures();
foreach (const QFuture<void> &future, futures) {
if (! (future.isFinished() || future.isCanceled()))
m_synchronizer.addFuture(future);
}
}
m_synchronizer.addFuture(result);
if (sourceFiles.count() > 1) {
Core::ICore::progressManager()->addTask(result,
QCoreApplication::translate("IndexingSupport", "Parsing"),
QLatin1String(CppTools::Constants::TASK_INDEX));
}
return result;
}
private:
static void parse(QFutureInterface<void> &future,
CppPreprocessor *preproc,
QStringList files)
{
if (files.isEmpty())
return;
const Core::MimeDatabase *mimeDb = Core::ICore::mimeDatabase();
Core::MimeType cSourceTy = mimeDb->findByType(QLatin1String("text/x-csrc"));
Core::MimeType cppSourceTy = mimeDb->findByType(QLatin1String("text/x-c++src"));
Core::MimeType mSourceTy = mimeDb->findByType(QLatin1String("text/x-objcsrc"));
QStringList sources;
QStringList headers;
QStringList suffixes = cSourceTy.suffixes();
suffixes += cppSourceTy.suffixes();
suffixes += mSourceTy.suffixes();
foreach (const QString &file, files) {
QFileInfo info(file);
preproc->snapshot.remove(file);
if (suffixes.contains(info.suffix()))
sources.append(file);
else
headers.append(file);
}
const int sourceCount = sources.size();
files = sources;
files += headers;
preproc->setTodo(files);
future.setProgressRange(0, files.size());
QString conf = QLatin1String(pp_configuration_file);
bool processingHeaders = false;
for (int i = 0; i < files.size(); ++i) {
if (future.isPaused())
future.waitForResume();
if (future.isCanceled())
break;
const QString fileName = files.at(i);
const bool isSourceFile = i < sourceCount;
if (isSourceFile)
(void) preproc->run(conf);
else if (! processingHeaders) {
(void) preproc->run(conf);
processingHeaders = true;
}
preproc->run(fileName);
future.setProgressValue(files.size() - preproc->todo().size());
if (isSourceFile)
preproc->resetEnvironment();
}
future.setProgressValue(files.size());
preproc->modelManager()->finishedRefreshingSourceFiles(files);
delete preproc;
}
private:
QFutureSynchronizer<void> m_synchronizer;
unsigned m_revision;
bool m_dumpFileNameWhileParsing;
};
} // anonymous namespace
/*!
\class CppTools::CppModelManager
\brief The CppModelManager keeps track of one CppCodeModel instance
......@@ -825,6 +688,9 @@ CppModelManager *CppModelManager::instance()
CppModelManager::CppModelManager(QObject *parent)
: CppModelManagerInterface(parent)
, m_completionAssistProvider(0)
, m_highlightingFactory(0)
, m_indexingSupporter(0)
{
m_findReferences = new CppFindReferences(this);
m_indexerEnabled = qgetenv("QTCREATOR_NO_CODE_INDEXER").isNull();
......@@ -872,7 +738,7 @@ CppModelManager::CppModelManager(QObject *parent)
ExtensionSystem::PluginManager::addObject(m_completionAssistProvider);
m_highlightingFallback = new CppHighlightingSupportInternalFactory;
m_highlightingFactory = m_highlightingFallback;
m_internalIndexingSupport = new IndexingSupport;
m_internalIndexingSupport = new BuiltinIndexingSupport(pp_configuration_file);
}
CppModelManager::~CppModelManager()
......@@ -1073,9 +939,8 @@ QFuture<void> CppModelManager::updateSourceFiles(const QStringList &sourceFiles)
if (sourceFiles.isEmpty() || !m_indexerEnabled)
return QFuture<void>();
foreach (CppIndexingSupport *indexer, m_indexingSupporters)
indexer->refreshSourceFiles(sourceFiles);
if (m_indexingSupporter)
m_indexingSupporter->refreshSourceFiles(sourceFiles);
return m_internalIndexingSupport->refreshSourceFiles(sourceFiles);
}
......@@ -1450,10 +1315,15 @@ void CppModelManager::setHighlightingSupportFactory(CppHighlightingSupportFactor
m_highlightingFactory = m_highlightingFallback;
}
void CppModelManager::addIndexingSupport(CppIndexingSupport *indexingSupport)
void CppModelManager::setIndexingSupport(CppIndexingSupport *indexingSupport)
{
if (indexingSupport)
m_indexingSupporters.append(indexingSupport);
m_indexingSupporter = indexingSupport;
}
CppIndexingSupport *CppModelManager::indexingSupport()
{
return m_indexingSupporter ? m_indexingSupporter : m_internalIndexingSupport;
}
void CppModelManager::setExtraDiagnostics(const QString &fileName, int kind,
......
......@@ -131,7 +131,8 @@ public:
virtual CppHighlightingSupport *highlightingSupport(Core::IEditor *editor) const;
virtual void setHighlightingSupportFactory(CppHighlightingSupportFactory *highlightingFactory);
virtual void addIndexingSupport(CppIndexingSupport *indexingSupport);
virtual void setIndexingSupport(CppIndexingSupport *indexingSupport);
virtual CppIndexingSupport *indexingSupport();
QStringList projectFiles()
{
......@@ -243,7 +244,7 @@ private:
CppCompletionAssistProvider *m_completionFallback;
CppHighlightingSupportFactory *m_highlightingFactory;
CppHighlightingSupportFactory *m_highlightingFallback;
QList<CppIndexingSupport *> m_indexingSupporters;
CppIndexingSupport *m_indexingSupporter;
CppIndexingSupport *m_internalIndexingSupport;
};
......
......@@ -47,7 +47,8 @@ HEADERS += completionsettingspage.h \
cppcompletionassistprovider.h \
ModelManagerInterface.h \
TypeHierarchyBuilder.h \
cppindexingsupport.h
cppindexingsupport.h \
builtinindexingsupport.h
SOURCES += completionsettingspage.cpp \
cppclassesfilter.cpp \
......@@ -87,7 +88,8 @@ SOURCES += completionsettingspage.cpp \
cppcompletionassistprovider.cpp \
ModelManagerInterface.cpp \
TypeHierarchyBuilder.cpp \
cppindexingsupport.cpp
cppindexingsupport.cpp \
builtinindexingsupport.cpp
FORMS += completionsettingspage.ui \
cppfilesettingspage.ui \
......
......@@ -39,13 +39,13 @@ using namespace CPlusPlus;
using namespace CppTools;
SearchSymbols::SymbolTypes SearchSymbols::AllTypes =
SearchSymbols::Classes
| SearchSymbols::Functions
| SearchSymbols::Enums
| SearchSymbols::Declarations;
SymbolSearcher::Classes
| SymbolSearcher::Functions
| SymbolSearcher::Enums
| SymbolSearcher::Declarations;