diff --git a/src/plugins/cpptools/builtinindexingsupport.cpp b/src/plugins/cpptools/builtinindexingsupport.cpp index 60a33ad7ad0..fc51ad12f90 100644 --- a/src/plugins/cpptools/builtinindexingsupport.cpp +++ b/src/plugins/cpptools/builtinindexingsupport.cpp @@ -125,7 +125,7 @@ public: break; if (m_fileNames.isEmpty() || m_fileNames.contains(it.value()->fileName())) { QVector resultItems; - search(it.value())->visitAllChildren([&](const IndexItem::Ptr &info) { + auto filter = [&](const IndexItem::Ptr &info) -> IndexItem::VisitorResult { if (matcher.indexIn(info->symbolName()) != -1) { QString text = info->symbolName(); QString scope = info->symbolScope(); @@ -148,7 +148,10 @@ public: item.userData = qVariantFromValue(info); resultItems << item; } - }); + + return IndexItem::Recurse; + }; + search(it.value())->visitAllChildren(filter); if (!resultItems.isEmpty()) future.reportResults(resultItems); } diff --git a/src/plugins/cpptools/cppclassesfilter.cpp b/src/plugins/cpptools/cppclassesfilter.cpp index 5835b4346b5..46519f63da5 100644 --- a/src/plugins/cpptools/cppclassesfilter.cpp +++ b/src/plugins/cpptools/cppclassesfilter.cpp @@ -45,11 +45,6 @@ CppClassesFilter::~CppClassesFilter() { } -QList > CppClassesFilter::itemsToMatchUserInputAgainst() const -{ - return QList >() << m_data->classes(); -} - Core::LocatorFilterEntry CppClassesFilter::filterEntryFromIndexItem(IndexItem::Ptr info) { const QVariant id = qVariantFromValue(info); diff --git a/src/plugins/cpptools/cppclassesfilter.h b/src/plugins/cpptools/cppclassesfilter.h index 446a90b7cae..7fd99416a09 100644 --- a/src/plugins/cpptools/cppclassesfilter.h +++ b/src/plugins/cpptools/cppclassesfilter.h @@ -34,19 +34,22 @@ #include "cpplocatordata.h" #include "cpplocatorfilter.h" +#include + namespace CppTools { +// TODO: un-export this class CPPTOOLS_EXPORT CppClassesFilter : public Internal::CppLocatorFilter { Q_OBJECT public: - CppClassesFilter(Internal::CppLocatorData *locatorData); - ~CppClassesFilter(); + CppClassesFilter(CppLocatorData *locatorData); + ~CppClassesFilter() QTC_OVERRIDE; -private: - QList > itemsToMatchUserInputAgainst() const; - Core::LocatorFilterEntry filterEntryFromIndexItem(IndexItem::Ptr info); +protected: + IndexItem::ItemType matchTypes() const QTC_OVERRIDE { return IndexItem::Class; } + Core::LocatorFilterEntry filterEntryFromIndexItem(IndexItem::Ptr info) QTC_OVERRIDE; }; } // namespace CppTools diff --git a/src/plugins/cpptools/cppcurrentdocumentfilter.cpp b/src/plugins/cpptools/cppcurrentdocumentfilter.cpp index ef3242c15d8..cd20cfdc547 100644 --- a/src/plugins/cpptools/cppcurrentdocumentfilter.cpp +++ b/src/plugins/cpptools/cppcurrentdocumentfilter.cpp @@ -78,10 +78,13 @@ QList CppCurrentDocumentFilter::matchesFor( if (m_itemsOfCurrentDoc.isEmpty()) { Snapshot snapshot = m_modelManager->snapshot(); Document::Ptr thisDocument = snapshot.document(m_currentFileName); - if (thisDocument) - search(thisDocument)->visitAllChildren([&](const IndexItem::Ptr &info){ + if (thisDocument) { + IndexItem::Ptr rootNode = search(thisDocument); + rootNode->visitAllChildren([&](const IndexItem::Ptr &info) -> IndexItem::VisitorResult { m_itemsOfCurrentDoc.append(info); + return IndexItem::Recurse; }); + } } const Qt::CaseSensitivity caseSensitivityForPrefix = caseSensitivity(entry); diff --git a/src/plugins/cpptools/cppfunctionsfilter.cpp b/src/plugins/cpptools/cppfunctionsfilter.cpp index ecdb8a971cf..883766bc41f 100644 --- a/src/plugins/cpptools/cppfunctionsfilter.cpp +++ b/src/plugins/cpptools/cppfunctionsfilter.cpp @@ -45,11 +45,6 @@ CppFunctionsFilter::~CppFunctionsFilter() { } -QList > CppFunctionsFilter::itemsToMatchUserInputAgainst() const -{ - return QList >() << m_data->functions(); -} - Core::LocatorFilterEntry CppFunctionsFilter::filterEntryFromIndexItem(IndexItem::Ptr info) { const QVariant id = qVariantFromValue(info); diff --git a/src/plugins/cpptools/cppfunctionsfilter.h b/src/plugins/cpptools/cppfunctionsfilter.h index ba0f9d49dbd..d024afc4e15 100644 --- a/src/plugins/cpptools/cppfunctionsfilter.h +++ b/src/plugins/cpptools/cppfunctionsfilter.h @@ -33,6 +33,8 @@ #include "cpplocatordata.h" #include "cpplocatorfilter.h" +#include + namespace CppTools { namespace Internal { @@ -42,11 +44,11 @@ class CppFunctionsFilter : public CppLocatorFilter public: CppFunctionsFilter(CppLocatorData *locatorData); - ~CppFunctionsFilter(); + ~CppFunctionsFilter() QTC_OVERRIDE; -private: - QList > itemsToMatchUserInputAgainst() const; - Core::LocatorFilterEntry filterEntryFromIndexItem(IndexItem::Ptr info); +protected: + IndexItem::ItemType matchTypes() const QTC_OVERRIDE { return IndexItem::Function; } + Core::LocatorFilterEntry filterEntryFromIndexItem(IndexItem::Ptr info) QTC_OVERRIDE; }; } // namespace Internal diff --git a/src/plugins/cpptools/cpplocatordata.cpp b/src/plugins/cpptools/cpplocatordata.cpp index 986834274db..26665916b36 100644 --- a/src/plugins/cpptools/cpplocatordata.cpp +++ b/src/plugins/cpptools/cpplocatordata.cpp @@ -33,42 +33,17 @@ using namespace CppTools; using namespace CppTools::Internal; -static const int MaxPendingDocuments = 10; +enum { MaxPendingDocuments = 10 }; -CppLocatorData::CppLocatorData(CppModelManager *modelManager) - : m_modelManager(modelManager) - , m_strings(CppToolsPlugin::stringTable()) - , m_search(m_strings) +CppLocatorData::CppLocatorData() + : m_strings(&CppToolsPlugin::stringTable()) + , m_search(CppToolsPlugin::stringTable()) , m_pendingDocumentsMutex(QMutex::Recursive) { - m_search.setSymbolsToSearchFor(SymbolSearcher::Enums - | SymbolSearcher::Classes - | SymbolSearcher::Functions); + m_search.setSymbolsToSearchFor(SymbolSearcher::Enums | + SymbolSearcher::Classes | + SymbolSearcher::Functions); m_pendingDocuments.reserve(MaxPendingDocuments); - - connect(m_modelManager, SIGNAL(documentUpdated(CPlusPlus::Document::Ptr)), - this, SLOT(onDocumentUpdated(CPlusPlus::Document::Ptr))); - - connect(m_modelManager, SIGNAL(aboutToRemoveFiles(QStringList)), - this, SLOT(onAboutToRemoveFiles(QStringList))); -} - -QList CppLocatorData::enums() -{ - flushPendingDocument(true); - return allIndexItems(m_allEnums); -} - -QList CppLocatorData::classes() -{ - flushPendingDocument(true); - return allIndexItems(m_allClasses); -} - -QList CppLocatorData::functions() -{ - flushPendingDocument(true); - return allIndexItems(m_allFunctions); } void CppLocatorData::onDocumentUpdated(const CPlusPlus::Document::Ptr &document) @@ -93,57 +68,37 @@ void CppLocatorData::onDocumentUpdated(const CPlusPlus::Document::Ptr &document) void CppLocatorData::onAboutToRemoveFiles(const QStringList &files) { + if (files.isEmpty()) + return; + QMutexLocker locker(&m_pendingDocumentsMutex); - for (int i = 0; i < m_pendingDocuments.size(); ) { - if (files.contains(m_pendingDocuments.at(i)->fileName())) - m_pendingDocuments.remove(i); - else - ++i; - } - foreach (const QString &file, files) { - m_allEnums.remove(file); - m_allClasses.remove(file); - m_allFunctions.remove(file); + m_infosByFile.remove(file); + + for (int i = 0; i < m_pendingDocuments.size(); ++i) { + if (m_pendingDocuments.at(i)->fileName() == file) { + m_pendingDocuments.remove(i); + break; + } + } } - m_strings.scheduleGC(); + m_strings->scheduleGC(); + flushPendingDocument(false); } -void CppLocatorData::flushPendingDocument(bool force) +void CppLocatorData::flushPendingDocument(bool force) const { + // TODO: move this off the UI thread and into a future. QMutexLocker locker(&m_pendingDocumentsMutex); if (!force && m_pendingDocuments.size() < MaxPendingDocuments) return; + if (m_pendingDocuments.isEmpty()) + return; - foreach (CPlusPlus::Document::Ptr doc, m_pendingDocuments) { - const QString fileName = findOrInsertFilePath(doc->fileName()); - - QList resultsEnums; - QList resultsClasses; - QList resultsFunctions; - - m_search(doc)->visitAllChildren([&](const IndexItem::Ptr &info) { - switch (info->type()) { - case IndexItem::Enum: - resultsEnums.append(info); - break; - case IndexItem::Class: - resultsClasses.append(info); - break; - case IndexItem::Function: - resultsFunctions.append(info); - break; - default: - break; - } - }); - - m_allEnums[fileName] = resultsEnums; - m_allClasses[fileName] = resultsClasses; - m_allFunctions[fileName] = resultsFunctions; - } + foreach (CPlusPlus::Document::Ptr doc, m_pendingDocuments) + m_infosByFile.insert(findOrInsertFilePath(doc->fileName()), m_search(doc)); m_pendingDocuments.clear(); m_pendingDocuments.reserve(MaxPendingDocuments); diff --git a/src/plugins/cpptools/cpplocatordata.h b/src/plugins/cpptools/cpplocatordata.h index 0feda706c4f..97fce390ce0 100644 --- a/src/plugins/cpptools/cpplocatordata.h +++ b/src/plugins/cpptools/cpplocatordata.h @@ -27,58 +27,66 @@ ** ****************************************************************************/ - #ifndef CPPLOCATORDATA_H #define CPPLOCATORDATA_H +#include #include -#include #include +#include "cpptools_global.h" #include "cppmodelmanager.h" #include "searchsymbols.h" #include "stringtable.h" namespace CppTools { + namespace Internal { +class CppToolsPlugin; +} // Internal namespace class CppLocatorData : public QObject { Q_OBJECT + + // Only one instance, created by the CppToolsPlugin. + CppLocatorData(); + friend class Internal::CppToolsPlugin; + public: - explicit CppLocatorData(CppModelManager *modelManager); + void filterAllFiles(IndexItem::Visitor func) const + { + flushPendingDocument(true); + QMutexLocker locker(&m_pendingDocumentsMutex); + QHash infosByFile = m_infosByFile; + locker.unlock(); + for (auto i = infosByFile.constBegin(), ei = infosByFile.constEnd(); i != ei; ++i) + if (i.value()->visitAllChildren(func) == IndexItem::Break) + return; + } - QList enums(); - QList classes(); - QList functions(); - -private slots: +public slots: void onDocumentUpdated(const CPlusPlus::Document::Ptr &document); void onAboutToRemoveFiles(const QStringList &files); private: - void flushPendingDocument(bool force); + void flushPendingDocument(bool force) const; QList allIndexItems(const QHash> &items) const; - QString findOrInsertFilePath(const QString &path) - { return m_strings.insert(path); } + QString findOrInsertFilePath(const QString &path) const + { return m_strings->insert(path); } private: - CppModelManager *m_modelManager; + Internal::StringTable *m_strings; // Used to avoid QString duplication - StringTable &m_strings; // Used to avoid QString duplication - - SearchSymbols m_search; - QHash > m_allEnums; - QHash > m_allClasses; - QHash > m_allFunctions; + mutable SearchSymbols m_search; + mutable QHash m_infosByFile; mutable QMutex m_pendingDocumentsMutex; - QVector m_pendingDocuments; + mutable QVector m_pendingDocuments; }; -} // namespace Internal -} // namespace CppTools +} // CppTools namespace #endif // CPPLOCATORDATA_H diff --git a/src/plugins/cpptools/cpplocatorfilter.cpp b/src/plugins/cpptools/cpplocatorfilter.cpp index 3c967c4d32f..1d36047a846 100644 --- a/src/plugins/cpptools/cpplocatorfilter.cpp +++ b/src/plugins/cpptools/cpplocatorfilter.cpp @@ -65,14 +65,6 @@ void CppLocatorFilter::refresh(QFutureInterface &future) Q_UNUSED(future) } -QList > CppLocatorFilter::itemsToMatchUserInputAgainst() const -{ - return QList >() - << m_data->classes() - << m_data->functions() - << m_data->enums(); -} - static bool compareLexigraphically(const Core::LocatorFilterEntry &a, const Core::LocatorFilterEntry &b) { @@ -93,16 +85,15 @@ QList CppLocatorFilter::matchesFor( bool hasWildcard = (entry.contains(asterisk) || entry.contains(QLatin1Char('?'))); bool hasColonColon = entry.contains(QLatin1String("::")); const Qt::CaseSensitivity caseSensitivityForPrefix = caseSensitivity(entry); + const IndexItem::ItemType wanted = matchTypes(); - const QList > itemLists = itemsToMatchUserInputAgainst(); - foreach (const QList &items, itemLists) { - foreach (IndexItem::Ptr info, items) { - if (future.isCanceled()) - break; - const QString matchString = hasColonColon ? info->scopedSymbolName() - : info->symbolName(); - if ((hasWildcard && regexp.exactMatch(matchString)) - || (!hasWildcard && matcher.indexIn(matchString) != -1)) { + m_data->filterAllFiles([&](const IndexItem::Ptr &info) -> IndexItem::VisitorResult { + if (future.isCanceled()) + return IndexItem::Break; + if (info->type() & wanted) { + const QString matchString = hasColonColon ? info->scopedSymbolName() : info->symbolName(); + if ((hasWildcard && regexp.exactMatch(matchString)) || + (!hasWildcard && matcher.indexIn(matchString) != -1)) { const Core::LocatorFilterEntry filterEntry = filterEntryFromIndexItem(info); if (matchString.startsWith(entry, caseSensitivityForPrefix)) betterEntries.append(filterEntry); @@ -110,7 +101,12 @@ QList CppLocatorFilter::matchesFor( goodEntries.append(filterEntry); } } - } + + if (info->type() & IndexItem::Enum) + return IndexItem::Continue; + else + return IndexItem::Recurse; + }); if (goodEntries.size() < 1000) qStableSort(goodEntries.begin(), goodEntries.end(), compareLexigraphically); diff --git a/src/plugins/cpptools/cpplocatorfilter.h b/src/plugins/cpptools/cpplocatorfilter.h index 07d5ce5fb23..dbf7eed6f04 100644 --- a/src/plugins/cpptools/cpplocatorfilter.h +++ b/src/plugins/cpptools/cpplocatorfilter.h @@ -54,7 +54,7 @@ public: void refresh(QFutureInterface &future); protected: - virtual QList > itemsToMatchUserInputAgainst() const; + virtual IndexItem::ItemType matchTypes() const { return IndexItem::All; } virtual Core::LocatorFilterEntry filterEntryFromIndexItem(IndexItem::Ptr info); protected: diff --git a/src/plugins/cpptools/cpptoolsplugin.cpp b/src/plugins/cpptools/cpptoolsplugin.cpp index 7e9f1d061d9..44179a1fb4c 100644 --- a/src/plugins/cpptools/cpptoolsplugin.cpp +++ b/src/plugins/cpptools/cpptoolsplugin.cpp @@ -131,7 +131,13 @@ bool CppToolsPlugin::initialize(const QStringList &arguments, QString *error) connect(DocumentManager::instance(), SIGNAL(filesChangedInternally(QStringList)), modelManager, SLOT(updateSourceFiles(QStringList))); - CppLocatorData *locatorData = new CppLocatorData(modelManager); + CppLocatorData *locatorData = new CppLocatorData; + connect(modelManager, SIGNAL(documentUpdated(CPlusPlus::Document::Ptr)), + locatorData, SLOT(onDocumentUpdated(CPlusPlus::Document::Ptr))); + + connect(modelManager, SIGNAL(aboutToRemoveFiles(QStringList)), + locatorData, SLOT(onAboutToRemoveFiles(QStringList))); + addAutoReleasedObject(locatorData); addAutoReleasedObject(new CppLocatorFilter(locatorData)); addAutoReleasedObject(new CppClassesFilter(locatorData)); diff --git a/src/plugins/cpptools/indexitem.cpp b/src/plugins/cpptools/indexitem.cpp index 66784975d0f..4790378479c 100644 --- a/src/plugins/cpptools/indexitem.cpp +++ b/src/plugins/cpptools/indexitem.cpp @@ -44,12 +44,3 @@ void IndexItem::squeeze() for (int i = 0, ei = m_children.size(); i != ei; ++i) m_children[i]->squeeze(); } - -void IndexItem::visitAllChildren(std::function f) const -{ - foreach (const IndexItem::Ptr &child, m_children) { - f(child); - if (!child->m_children.isEmpty()) - child->visitAllChildren(f); - } -} diff --git a/src/plugins/cpptools/indexitem.h b/src/plugins/cpptools/indexitem.h index 2ebf070f4ba..40b9782e8c0 100644 --- a/src/plugins/cpptools/indexitem.h +++ b/src/plugins/cpptools/indexitem.h @@ -38,6 +38,8 @@ #include #include +#include + namespace CppTools { class CPPTOOLS_EXPORT IndexItem @@ -45,7 +47,14 @@ class CPPTOOLS_EXPORT IndexItem Q_DISABLE_COPY(IndexItem) public: - enum ItemType { Enum, Class, Function, Declaration }; + enum ItemType { + Enum = 1 << 0, + Class = 1 << 1, + Function = 1 << 2, + Declaration = 1 << 3, + + All = Enum | Class | Function | Declaration + }; private: IndexItem(const QString &symbolName, @@ -139,7 +148,34 @@ public: void addChild(IndexItem::Ptr childItem) { m_children.append(childItem); } void squeeze(); - void visitAllChildren(std::function f) const; + enum VisitorResult { + Break, /// terminates traversal + Continue, /// continues traversal with the next sibling + Recurse, /// continues traversal with the children + }; + + typedef std::function Visitor; + + VisitorResult visitAllChildren(Visitor callback) const + { + VisitorResult result = Recurse; + foreach (const IndexItem::Ptr &child, m_children) { + result = callback(child); + switch (result) { + case Break: + return Break; + case Continue: + continue; + case Recurse: + if (!child->m_children.isEmpty()) { + result = child->visitAllChildren(callback); + if (result == Break) + return Break; + } + } + } + return result; + } private: QString m_symbolName; // as found in the code, therefore might be qualified