Commit 536ccc8a authored by Nikolai Kosjar's avatar Nikolai Kosjar

CppTools: Fix incompletely indexed project

Use case to reproduce:
 1. Open some bigger project, e.g. qtcreator.pro
 2. As soon as "Parsing C/C++ files" is reported, add a character to
    qmake's additional arguments in project mode (indexing should not be
    finished at this point).
 3. The indexing gets canceled.
 ==> ...but reindexing is not triggered.

Fix by checking whether the future was canceled.

Task-number: QTCREATORBUG-16134
Change-Id: I520c6a64a6adc1cb04cafb5e0aa56c8bf41d7b14
Reviewed-by: Christian Stenger's avatarChristian Stenger <christian.stenger@qt.io>
parent e8b53898
...@@ -56,6 +56,7 @@ ...@@ -56,6 +56,7 @@
#include <QCoreApplication> #include <QCoreApplication>
#include <QDebug> #include <QDebug>
#include <QDir> #include <QDir>
#include <QFutureWatcher>
#include <QMutexLocker> #include <QMutexLocker>
#include <QTextBlock> #include <QTextBlock>
#include <QThreadPool> #include <QThreadPool>
...@@ -131,6 +132,7 @@ public: ...@@ -131,6 +132,7 @@ public:
// Project integration // Project integration
mutable QMutex m_projectMutex; mutable QMutex m_projectMutex;
QMap<ProjectExplorer::Project *, ProjectInfo> m_projectToProjectsInfo; QMap<ProjectExplorer::Project *, ProjectInfo> m_projectToProjectsInfo;
QHash<ProjectExplorer::Project *, bool> m_projectToIndexerCanceled;
QMap<Utils::FileName, QList<ProjectPart::Ptr> > m_fileToProjectParts; QMap<Utils::FileName, QList<ProjectPart::Ptr> > m_fileToProjectParts;
QMap<QString, ProjectPart::Ptr> m_projectPartIdToProjectProjectPart; QMap<QString, ProjectPart::Ptr> m_projectPartIdToProjectProjectPart;
// The members below are cached/(re)calculated from the projects and/or their project parts // The members below are cached/(re)calculated from the projects and/or their project parts
...@@ -759,6 +761,25 @@ void CppModelManager::recalculateProjectPartMappings() ...@@ -759,6 +761,25 @@ void CppModelManager::recalculateProjectPartMappings()
d->m_symbolFinder.clearCache(); d->m_symbolFinder.clearCache();
} }
void CppModelManager::watchForCanceledProjectIndexer(QFuture<void> future,
ProjectExplorer::Project *project)
{
d->m_projectToIndexerCanceled.insert(project, false);
if (future.isCanceled() || future.isFinished())
return;
QFutureWatcher<void> *watcher = new QFutureWatcher<void>();
connect(watcher, &QFutureWatcher<void>::canceled, this, [this, project]() {
if (d->m_projectToIndexerCanceled.contains(project)) // Project not yet removed
d->m_projectToIndexerCanceled.insert(project, true);
});
connect(watcher, &QFutureWatcher<void>::finished, this, [watcher]() {
watcher->deleteLater();
});
watcher->setFuture(future);
}
void CppModelManager::updateCppEditorDocuments() const void CppModelManager::updateCppEditorDocuments() const
{ {
// Refresh visible documents // Refresh visible documents
...@@ -792,16 +813,17 @@ QFuture<void> CppModelManager::updateProjectInfo(const ProjectInfo &newProjectIn ...@@ -792,16 +813,17 @@ QFuture<void> CppModelManager::updateProjectInfo(const ProjectInfo &newProjectIn
QSet<QString> filesToReindex; QSet<QString> filesToReindex;
QStringList removedProjectParts; QStringList removedProjectParts;
bool filesRemoved = false; bool filesRemoved = false;
ProjectExplorer::Project *project = newProjectInfo.project().data();
{ // Only hold the mutex for a limited scope, so the dumping afterwards does not deadlock. { // Only hold the mutex for a limited scope, so the dumping afterwards does not deadlock.
QMutexLocker projectLocker(&d->m_projectMutex); QMutexLocker projectLocker(&d->m_projectMutex);
ProjectExplorer::Project *project = newProjectInfo.project().data();
const QSet<QString> newSourceFiles = newProjectInfo.sourceFiles(); const QSet<QString> newSourceFiles = newProjectInfo.sourceFiles();
// Check if we can avoid a full reindexing // Check if we can avoid a full reindexing
ProjectInfo oldProjectInfo = d->m_projectToProjectsInfo.value(project); ProjectInfo oldProjectInfo = d->m_projectToProjectsInfo.value(project);
if (oldProjectInfo.isValid()) { const bool previousIndexerCanceled = d->m_projectToIndexerCanceled.value(project, false);
if (!previousIndexerCanceled && oldProjectInfo.isValid()) {
ProjectInfoComparer comparer(oldProjectInfo, newProjectInfo); ProjectInfoComparer comparer(oldProjectInfo, newProjectInfo);
if (comparer.configurationOrFilesChanged()) { if (comparer.configurationOrFilesChanged()) {
...@@ -872,7 +894,10 @@ QFuture<void> CppModelManager::updateProjectInfo(const ProjectInfo &newProjectIn ...@@ -872,7 +894,10 @@ QFuture<void> CppModelManager::updateProjectInfo(const ProjectInfo &newProjectIn
updateCppEditorDocuments(); updateCppEditorDocuments();
// Trigger reindexing // Trigger reindexing
return updateSourceFiles(filesToReindex, ForcedProgressNotification); QFuture<void> indexerFuture = updateSourceFiles(filesToReindex, ForcedProgressNotification);
watchForCanceledProjectIndexer(indexerFuture, project);
return indexerFuture;
} }
ProjectPart::Ptr CppModelManager::projectPartForId(const QString &projectPartId) const ProjectPart::Ptr CppModelManager::projectPartForId(const QString &projectPartId) const
...@@ -970,6 +995,8 @@ void CppModelManager::onAboutToRemoveProject(ProjectExplorer::Project *project) ...@@ -970,6 +995,8 @@ void CppModelManager::onAboutToRemoveProject(ProjectExplorer::Project *project)
{ {
QStringList projectPartIds; QStringList projectPartIds;
d->m_projectToIndexerCanceled.remove(project);
{ {
QMutexLocker locker(&d->m_projectMutex); QMutexLocker locker(&d->m_projectMutex);
d->m_dirty = true; d->m_dirty = true;
......
...@@ -206,6 +206,7 @@ private: ...@@ -206,6 +206,7 @@ private:
void initializeBuiltinModelManagerSupport(); void initializeBuiltinModelManagerSupport();
void delayedGC(); void delayedGC();
void recalculateProjectPartMappings(); void recalculateProjectPartMappings();
void watchForCanceledProjectIndexer(QFuture<void> future, ProjectExplorer::Project *project);
void replaceSnapshot(const CPlusPlus::Snapshot &newSnapshot); void replaceSnapshot(const CPlusPlus::Snapshot &newSnapshot);
void removeFilesFromSnapshot(const QSet<QString> &removedFiles); void removeFilesFromSnapshot(const QSet<QString> &removedFiles);
......
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