aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/plugins/cpptools/cppmodelmanager.cpp185
-rw-r--r--src/plugins/cpptools/cppmodelmanager.h7
-rw-r--r--src/plugins/cpptools/cppmodelmanager_test.cpp214
-rw-r--r--src/plugins/cpptools/cppmodelmanagerinterface.cpp31
-rw-r--r--src/plugins/cpptools/cppmodelmanagerinterface.h7
-rw-r--r--src/plugins/cpptools/cpptoolsplugin.h3
-rw-r--r--tests/cppmodelmanager/testdata_refresh2/source.cpp1
-rw-r--r--tests/cppmodelmanager/testdata_refresh2/source2.cpp1
8 files changed, 417 insertions, 32 deletions
diff --git a/src/plugins/cpptools/cppmodelmanager.cpp b/src/plugins/cpptools/cppmodelmanager.cpp
index d9f53f2f5d2..b22c42fdaa8 100644
--- a/src/plugins/cpptools/cppmodelmanager.cpp
+++ b/src/plugins/cpptools/cppmodelmanager.cpp
@@ -172,12 +172,11 @@ static const char pp_configuration[] =
"#define __inline inline\n"
"#define __forceinline inline\n";
-void CppModelManager::updateModifiedSourceFiles()
+QStringList CppModelManager::timeStampModifiedFiles(const QList<Document::Ptr> documentsToCheck)
{
- const Snapshot snapshot = this->snapshot();
QStringList sourceFiles;
- foreach (const Document::Ptr doc, snapshot) {
+ foreach (const Document::Ptr doc, documentsToCheck) {
const QDateTime lastModified = doc->lastModified();
if (!lastModified.isNull()) {
@@ -188,7 +187,18 @@ void CppModelManager::updateModifiedSourceFiles()
}
}
- updateSourceFiles(sourceFiles);
+ return sourceFiles;
+}
+
+void CppModelManager::updateModifiedSourceFiles()
+{
+ const Snapshot snapshot = this->snapshot();
+ QList<Document::Ptr> documentsToCheck;
+ foreach (const Document::Ptr document, snapshot)
+ documentsToCheck << document;
+
+ const QStringList filesToUpdate = timeStampModifiedFiles(documentsToCheck);
+ updateSourceFiles(filesToUpdate);
}
/*!
@@ -584,39 +594,155 @@ CppModelManager::ProjectInfo CppModelManager::projectInfo(ProjectExplorer::Proje
return m_projectToProjectsInfo.value(project, ProjectInfo(project));
}
-QFuture<void> CppModelManager::updateProjectInfo(const ProjectInfo &pinfo)
+/// \brief Remove all files and their includes (recursively) of given ProjectInfo from the snapshot.
+void CppModelManager::removeProjectInfoFilesAndIncludesFromSnapshot(const ProjectInfo &projectInfo)
+{
+ if (!projectInfo.isValid())
+ return;
+
+ QMutexLocker snapshotLocker(&m_snapshotMutex);
+ foreach (const ProjectPart::Ptr &projectPart, projectInfo.projectParts()) {
+ foreach (const ProjectFile &cxxFile, projectPart->files) {
+ foreach (const QString &fileName, m_snapshot.allIncludesForDocument(cxxFile.path))
+ m_snapshot.remove(fileName);
+ m_snapshot.remove(cxxFile.path);
+ }
+ }
+}
+
+/// \brief Remove all given files from the snapshot.
+void CppModelManager::removeFilesFromSnapshot(const QSet<QString> &filesToRemove)
+{
+ QMutexLocker snapshotLocker(&m_snapshotMutex);
+ QSetIterator<QString> i(filesToRemove);
+ while (i.hasNext())
+ m_snapshot.remove(i.next());
+}
+
+class ProjectInfoComparer
+{
+public:
+ ProjectInfoComparer(const CppModelManager::ProjectInfo &oldProjectInfo,
+ const CppModelManager::ProjectInfo &newProjectInfo)
+ : m_old(oldProjectInfo)
+ , m_oldSourceFiles(oldProjectInfo.sourceFiles().toSet())
+ , m_new(newProjectInfo)
+ , m_newSourceFiles(newProjectInfo.sourceFiles().toSet())
+ {}
+
+ bool definesChanged() const
+ {
+ return m_new.defines() != m_old.defines();
+ }
+
+ bool configurationChanged() const
+ {
+ return definesChanged()
+ || m_new.includePaths() != m_old.includePaths()
+ || m_new.frameworkPaths() != m_old.frameworkPaths();
+ }
+
+ bool nothingChanged() const
+ {
+ return !configurationChanged() && m_new.sourceFiles() == m_old.sourceFiles();
+ }
+
+ QSet<QString> addedFiles() const
+ {
+ QSet<QString> addedFilesSet = m_newSourceFiles;
+ addedFilesSet.subtract(m_oldSourceFiles);
+ return addedFilesSet;
+ }
+
+ QSet<QString> removedFiles() const
+ {
+ QSet<QString> removedFilesSet = m_oldSourceFiles;
+ removedFilesSet.subtract(m_newSourceFiles);
+ return removedFilesSet;
+ }
+
+ /// Returns a list of common files that have a changed timestamp.
+ QSet<QString> timeStampModifiedFiles(const Snapshot &snapshot) const
+ {
+ QSet<QString> commonSourceFiles = m_newSourceFiles;
+ commonSourceFiles.intersect(m_oldSourceFiles);
+
+ QList<Document::Ptr> documentsToCheck;
+ QSetIterator<QString> i(commonSourceFiles);
+ while (i.hasNext()) {
+ const QString file = i.next();
+ if (Document::Ptr document = snapshot.document(file))
+ documentsToCheck << document;
+ }
+
+ return CppModelManager::timeStampModifiedFiles(documentsToCheck).toSet();
+ }
+
+private:
+ const CppModelManager::ProjectInfo &m_old;
+ const QSet<QString> m_oldSourceFiles;
+
+ const CppModelManager::ProjectInfo &m_new;
+ const QSet<QString> m_newSourceFiles;
+};
+
+QFuture<void> CppModelManager::updateProjectInfo(const ProjectInfo &newProjectInfo)
{
- if (!pinfo.isValid())
+ if (!newProjectInfo.isValid())
return QFuture<void>();
+ QStringList filesToReindex;
+ bool filesRemoved = false;
+
{ // Only hold the mutex for a limited scope, so the dumping afterwards does not deadlock.
- QMutexLocker locker(&m_projectMutex);
+ QMutexLocker projectLocker(&m_projectMutex);
- ProjectExplorer::Project *project = pinfo.project().data();
+ ProjectExplorer::Project *project = newProjectInfo.project().data();
+ const QStringList newSourceFiles = newProjectInfo.sourceFiles();
+
+ // Check if we can avoid a full reindexing
ProjectInfo oldProjectInfo = m_projectToProjectsInfo.value(project);
if (oldProjectInfo.isValid()) {
- if (pinfo.defines() == oldProjectInfo.defines()
- && pinfo.includePaths() == oldProjectInfo.includePaths()
- && pinfo.frameworkPaths() == oldProjectInfo.frameworkPaths()
- && pinfo.sourceFiles() == oldProjectInfo.sourceFiles()) {
+ ProjectInfoComparer comparer(oldProjectInfo, newProjectInfo);
+ if (comparer.nothingChanged())
return QFuture<void>();
- }
- foreach (const ProjectPart::Ptr &projectPart, oldProjectInfo.projectParts()) {
- foreach (const ProjectFile &cxxFile, projectPart->files) {
- foreach (const QString &fileName,
- m_snapshot.allIncludesForDocument(cxxFile.path)) {
- m_snapshot.remove(fileName);
- }
- m_snapshot.remove(cxxFile.path);
+ // If the project configuration changed, do a full reindexing
+ if (comparer.configurationChanged()) {
+ removeProjectInfoFilesAndIncludesFromSnapshot(oldProjectInfo);
+ filesToReindex << newSourceFiles;
+
+ // The "configuration file" includes all defines and therefore should be updated
+ if (comparer.definesChanged()) {
+ QMutexLocker snapshotLocker(&m_snapshotMutex);
+ m_snapshot.remove(configurationFileName());
}
+
+ // Otherwise check for added and modified files
+ } else {
+ const QSet<QString> addedFiles = comparer.addedFiles();
+ filesToReindex << addedFiles.toList();
+
+ const QSet<QString> modifiedFiles = comparer.timeStampModifiedFiles(snapshot());
+ filesToReindex << modifiedFiles.toList();
}
+
+ // Announce and purge the removed files from the snapshot
+ const QSet<QString> removedFiles = comparer.removedFiles();
+ if (!removedFiles.isEmpty()) {
+ filesRemoved = true;
+ emit aboutToRemoveFiles(removedFiles.toList());
+ removeFilesFromSnapshot(removedFiles);
+ }
+
+ // A new project was opened/created, do a full indexing
+ } else {
+ filesToReindex << newSourceFiles;
}
- m_snapshot.remove(configurationFileName());
- m_projectToProjectsInfo.insert(project, pinfo);
+ // Update Project/ProjectInfo and File/ProjectPart table
m_dirty = true;
-
+ m_projectToProjectsInfo.insert(project, newProjectInfo);
m_fileToProjectParts.clear();
foreach (const ProjectInfo &projectInfo, m_projectToProjectsInfo) {
foreach (const ProjectPart::Ptr &projectPart, projectInfo.projectParts()) {
@@ -625,14 +751,21 @@ QFuture<void> CppModelManager::updateProjectInfo(const ProjectInfo &pinfo)
}
}
}
- }
+ } // Mutex scope
+
+ // If requested, dump everything we got
if (!qgetenv("QTCREATOR_DUMP_PROJECT_INFO").isEmpty())
dumpModelManagerConfiguration();
- emit projectPartsUpdated(pinfo.project().data());
+ // Remove files from snapshot that are not reachable any more
+ if (filesRemoved)
+ GC();
+
+ emit projectPartsUpdated(newProjectInfo.project().data());
- return updateSourceFiles(pinfo.sourceFiles(), ForcedProgressNotification);
+ // Trigger reindexing
+ return updateSourceFiles(filesToReindex, ForcedProgressNotification);
}
QList<ProjectPart::Ptr> CppModelManager::projectPart(const QString &fileName) const
diff --git a/src/plugins/cpptools/cppmodelmanager.h b/src/plugins/cpptools/cppmodelmanager.h
index 5c65a9781ad..249cfb65ac0 100644
--- a/src/plugins/cpptools/cppmodelmanager.h
+++ b/src/plugins/cpptools/cppmodelmanager.h
@@ -72,7 +72,7 @@ public:
virtual QList<ProjectInfo> projectInfos() const;
virtual ProjectInfo projectInfo(ProjectExplorer::Project *project) const;
- virtual QFuture<void> updateProjectInfo(const ProjectInfo &pinfo);
+ virtual QFuture<void> updateProjectInfo(const ProjectInfo &newProjectInfo);
virtual QList<CppTools::ProjectPart::Ptr> projectPart(const QString &fileName) const;
virtual CPlusPlus::Snapshot snapshot() const;
@@ -141,6 +141,8 @@ public:
return m_definedMacros;
}
+ static QStringList timeStampModifiedFiles(const QList<Document::Ptr> documentsToCheck);
+
signals:
void aboutToRemoveFiles(const QStringList &files);
void gcFinished(); // Needed for tests.
@@ -160,6 +162,9 @@ private slots:
private:
void delayedGC();
void replaceSnapshot(const CPlusPlus::Snapshot &newSnapshot);
+ void removeFilesFromSnapshot(const QSet<QString> &removedFiles);
+ void removeProjectInfoFilesAndIncludesFromSnapshot(const ProjectInfo &projectInfo);
+
WorkingCopy buildWorkingCopyList();
void ensureUpdated();
diff --git a/src/plugins/cpptools/cppmodelmanager_test.cpp b/src/plugins/cpptools/cppmodelmanager_test.cpp
index 1fb02ba5ed1..34c05f0ac7c 100644
--- a/src/plugins/cpptools/cppmodelmanager_test.cpp
+++ b/src/plugins/cpptools/cppmodelmanager_test.cpp
@@ -48,6 +48,8 @@ typedef CppTools::ProjectPart ProjectPart;
typedef CppTools::ProjectFile ProjectFile;
typedef ProjectExplorer::Project Project;
+Q_DECLARE_METATYPE(ProjectFile)
+
namespace {
class TestDataDirectory
@@ -176,6 +178,52 @@ private:
QString m_fileToRemove;
};
+/// Changes a file on the disk and restores its original contents on destruction
+class FileChangerAndRestorer
+{
+public:
+ FileChangerAndRestorer(const QString &filePath)
+ : m_filePath(filePath)
+ {
+ }
+
+ ~FileChangerAndRestorer()
+ {
+ restoreContents();
+ }
+
+ /// Saves the contents also internally so it can be restored on destruction
+ bool readContents(QByteArray *contents)
+ {
+ Utils::FileReader fileReader;
+ const bool isFetchOk = fileReader.fetch(m_filePath);
+ if (isFetchOk) {
+ m_originalFileContents = fileReader.data();
+ if (contents)
+ *contents = m_originalFileContents;
+ }
+ return isFetchOk;
+ }
+
+ void writeContents(const QByteArray &contents) const
+ {
+ Utils::FileSaver fileSaver(m_filePath);
+ fileSaver.write(contents);
+ fileSaver.finalize();
+ }
+
+private:
+ void restoreContents() const
+ {
+ Utils::FileSaver fileSaver(m_filePath);
+ fileSaver.write(m_originalFileContents);
+ fileSaver.finalize();
+ }
+
+ QByteArray m_originalFileContents;
+ const QString &m_filePath;
+};
+
} // anonymous namespace
/// Check: The preprocessor cleans include and framework paths.
@@ -232,8 +280,7 @@ void CppToolsPlugin::test_modelmanager_framework_headers()
part->files << ProjectFile(source, ProjectFile::CXXSource);
pi.appendProjectPart(part);
- mm->updateProjectInfo(pi);
- mm->updateSourceFiles(QStringList(source)).waitForFinished();
+ mm->updateProjectInfo(pi).waitForFinished();
QCoreApplication::processEvents();
QVERIFY(mm->snapshot().contains(source));
@@ -280,7 +327,6 @@ void CppToolsPlugin::test_modelmanager_refresh_also_includes_of_project_files()
part->includePaths = QStringList() << testDataDir.includeDir(false);
part->files.append(ProjectFile(testCpp, ProjectFile::CXXSource));
pi.appendProjectPart(part);
-
mm->updateProjectInfo(pi);
QStringList refreshedFiles = helper.waitForRefreshedSourceFiles();
@@ -301,6 +347,7 @@ void CppToolsPlugin::test_modelmanager_refresh_also_includes_of_project_files()
pi.clearProjectParts();
pi.appendProjectPart(part);
mm->updateProjectInfo(pi);
+
refreshedFiles = helper.waitForRefreshedSourceFiles();
QCOMPARE(refreshedFiles.size(), 1);
@@ -342,7 +389,6 @@ void CppToolsPlugin::test_modelmanager_refresh_several_times()
part->files.append(ProjectFile(testHeader2, ProjectFile::CXXHeader));
part->files.append(ProjectFile(testCpp, ProjectFile::CXXSource));
pi.appendProjectPart(part);
-
mm->updateProjectInfo(pi);
CPlusPlus::Snapshot snapshot;
@@ -364,6 +410,7 @@ void CppToolsPlugin::test_modelmanager_refresh_several_times()
pi.appendProjectPart(part);
mm->updateProjectInfo(pi);
+
refreshedFiles = helper.waitForRefreshedSourceFiles();
QCOMPARE(refreshedFiles.size(), 3);
@@ -420,6 +467,165 @@ void CppToolsPlugin::test_modelmanager_refresh_test_for_changes()
QVERIFY(subsequentFuture.isCanceled() && subsequentFuture.isFinished());
}
+/// Check: (1) Added project files are recognized and parsed.
+/// Check: (2) Removed project files are recognized and purged from the snapshot.
+void CppToolsPlugin::test_modelmanager_refresh_added_and_purge_removed()
+{
+ ModelManagerTestHelper helper;
+ CppModelManager *mm = CppModelManager::instance();
+
+ const TestDataDirectory testDataDir(QLatin1String("testdata_refresh"));
+
+ const QString testHeader1(testDataDir.file(QLatin1String("header.h")));
+ const QString testHeader2(testDataDir.file(QLatin1String("defines.h")));
+ const QString testCpp(testDataDir.file(QLatin1String("source.cpp")));
+
+ Project *project = helper.createProject(QLatin1String("test_modelmanager_refresh_3"));
+ ProjectInfo pi = mm->projectInfo(project);
+ QCOMPARE(pi.project().data(), project);
+
+ ProjectPart::Ptr part(new ProjectPart);
+ part->cxxVersion = ProjectPart::CXX98;
+ part->qtVersion = ProjectPart::Qt5;
+ part->files.append(ProjectFile(testCpp, ProjectFile::CXXSource));
+ part->files.append(ProjectFile(testHeader1, ProjectFile::CXXHeader));
+ pi.appendProjectPart(part);
+
+ CPlusPlus::Snapshot snapshot;
+ QStringList refreshedFiles;
+
+ mm->updateProjectInfo(pi);
+ refreshedFiles = helper.waitForRefreshedSourceFiles();
+
+ QCOMPARE(refreshedFiles.size(), 2);
+ QVERIFY(refreshedFiles.contains(testHeader1));
+ QVERIFY(refreshedFiles.contains(testCpp));
+
+ snapshot = mm->snapshot();
+ QVERIFY(snapshot.contains(testHeader1));
+ QVERIFY(snapshot.contains(testCpp));
+
+ // Now add testHeader2 and remove testHeader1
+ pi.clearProjectParts();
+ ProjectPart::Ptr newPart(new ProjectPart);
+ newPart->cxxVersion = ProjectPart::CXX98;
+ newPart->qtVersion = ProjectPart::Qt5;
+ newPart->files.append(ProjectFile(testCpp, ProjectFile::CXXSource));
+ newPart->files.append(ProjectFile(testHeader2, ProjectFile::CXXHeader));
+ pi.appendProjectPart(newPart);
+
+ mm->updateProjectInfo(pi);
+ refreshedFiles = helper.waitForRefreshedSourceFiles();
+
+ // Only the added project file was reparsed
+ QCOMPARE(refreshedFiles.size(), 1);
+ QVERIFY(refreshedFiles.contains(testHeader2));
+
+ snapshot = mm->snapshot();
+ QVERIFY(snapshot.contains(testHeader2));
+ QVERIFY(snapshot.contains(testCpp));
+ // The removed project file is not anymore in the snapshot
+ QVERIFY(!snapshot.contains(testHeader1));
+}
+
+/// Check: Timestamp modified files are reparsed if project files are added or removed
+/// while the project configuration stays the same
+void CppToolsPlugin::test_modelmanager_refresh_timeStampModified_if_sourcefiles_change()
+{
+ QFETCH(QString, fileToChange);
+ QFETCH(QList<ProjectFile>, initialProjectFiles);
+ QFETCH(QList<ProjectFile>, finalProjectFiles);
+
+ ModelManagerTestHelper helper;
+ CppModelManager *mm = CppModelManager::instance();
+
+ Project *project = helper.createProject(
+ QLatin1String("test_modelmanager_refresh_timeStampModified"));
+ ProjectInfo pi = mm->projectInfo(project);
+ QCOMPARE(pi.project().data(), project);
+
+ ProjectPart::Ptr part(new ProjectPart);
+ part->cxxVersion = ProjectPart::CXX98;
+ part->qtVersion = ProjectPart::Qt5;
+ foreach (const ProjectFile &file, initialProjectFiles)
+ part->files.append(file);
+ pi.appendProjectPart(part);
+
+ Document::Ptr document;
+ CPlusPlus::Snapshot snapshot;
+ QStringList refreshedFiles;
+
+ mm->updateProjectInfo(pi);
+ refreshedFiles = helper.waitForRefreshedSourceFiles();
+
+ QCOMPARE(refreshedFiles.size(), initialProjectFiles.size());
+ snapshot = mm->snapshot();
+ foreach (const ProjectFile &file, initialProjectFiles) {
+ QVERIFY(refreshedFiles.contains(file.path));
+ QVERIFY(snapshot.contains(file.path));
+ }
+
+ document = snapshot.document(fileToChange);
+ const QDateTime lastModifiedBefore = document->lastModified();
+ QCOMPARE(document->globalSymbolCount(), 1U);
+ QCOMPARE(document->globalSymbolAt(0)->name()->identifier()->chars(), "someGlobal");
+
+ // Modify the file
+ QTest::qSleep(1000); // Make sure the timestamp is different
+ FileChangerAndRestorer fileChangerAndRestorer(fileToChange);
+ QByteArray originalContents;
+ QVERIFY(fileChangerAndRestorer.readContents(&originalContents));
+ const QByteArray newFileContentes = originalContents + "\nint addedOtherGlobal;";
+ fileChangerAndRestorer.writeContents(newFileContentes);
+
+ // Add or remove source file. The configuration stays the same.
+ part->files.clear();
+ foreach (const ProjectFile &file, finalProjectFiles)
+ part->files.append(file);
+ pi.clearProjectParts();
+ pi.appendProjectPart(part);
+
+ mm->updateProjectInfo(pi);
+ refreshedFiles = helper.waitForRefreshedSourceFiles();
+
+ QCOMPARE(refreshedFiles.size(), finalProjectFiles.size());
+ snapshot = mm->snapshot();
+ foreach (const ProjectFile &file, finalProjectFiles) {
+ QVERIFY(refreshedFiles.contains(file.path));
+ QVERIFY(snapshot.contains(file.path));
+ }
+ document = snapshot.document(fileToChange);
+ const QDateTime lastModifiedAfter = document->lastModified();
+ QVERIFY(lastModifiedAfter > lastModifiedBefore);
+ QCOMPARE(document->globalSymbolCount(), 2U);
+ QCOMPARE(document->globalSymbolAt(0)->name()->identifier()->chars(), "someGlobal");
+ QCOMPARE(document->globalSymbolAt(1)->name()->identifier()->chars(), "addedOtherGlobal");
+}
+
+void CppToolsPlugin::test_modelmanager_refresh_timeStampModified_if_sourcefiles_change_data()
+{
+ QTest::addColumn<QString>("fileToChange");
+ QTest::addColumn<QList<ProjectFile> >("initialProjectFiles");
+ QTest::addColumn<QList<ProjectFile> >("finalProjectFiles");
+
+ const TestDataDirectory testDataDir(QLatin1String("testdata_refresh2"));
+ const QString testCpp(testDataDir.file(QLatin1String("source.cpp")));
+ const QString testCpp2(testDataDir.file(QLatin1String("source2.cpp")));
+
+ const QString fileToChange = testCpp;
+ QList<ProjectFile> projectFiles1 = QList<ProjectFile>()
+ << ProjectFile(testCpp, ProjectFile::CXXSource);
+ QList<ProjectFile> projectFiles2 = QList<ProjectFile>()
+ << ProjectFile(testCpp, ProjectFile::CXXSource)
+ << ProjectFile(testCpp2, ProjectFile::CXXSource);
+
+ // Add a file
+ QTest::newRow("case: add project file") << fileToChange << projectFiles1 << projectFiles2;
+
+ // Remove a file
+ QTest::newRow("case: remove project file") << fileToChange << projectFiles2 << projectFiles1;
+}
+
/// Check: If a second project is opened, the code model is still aware of
/// files of the first project.
void CppToolsPlugin::test_modelmanager_snapshot_after_two_projects()
diff --git a/src/plugins/cpptools/cppmodelmanagerinterface.cpp b/src/plugins/cpptools/cppmodelmanagerinterface.cpp
index 1338c214a12..cb5ba96e6d1 100644
--- a/src/plugins/cpptools/cppmodelmanagerinterface.cpp
+++ b/src/plugins/cpptools/cppmodelmanagerinterface.cpp
@@ -68,6 +68,37 @@ using namespace ProjectExplorer;
Parser may enable tricks for Qt v5.x
*/
+/*!
+ \fn virtual QFuture<void> updateProjectInfo(const ProjectInfo &pinfo) = 0;
+ \param pinfo Updated ProjectInfo.
+ \return A future that reports progress and allows to cancel the reparsing operation.
+
+ This function is expected to be called by the project managers to update the
+ code model with new project information.
+
+ In particular, the function should be called in case:
+ 1. A new project is opened/created
+ 2. The project configuration changed. This includes
+ 2.1 Changes of defines, includes, framework paths
+ 2.2 Addition/Removal of project files
+
+ \sa CppTools::CppModelManagerInterface::updateSourceFiles()
+*/
+
+/*!
+ \fn virtual QFuture<void> updateSourceFiles(const QStringList &sourceFiles, ProgressNotificationMode mode = ReservedProgressNotification) = 0;
+ \param sourceFiles List of source file to update. The items are absolute paths.
+ \param mode The progress modification mode.
+ \return A future that reports progress and allows to cancel the reparsing operation.
+
+ Trigger an asynchronous reparsing of the given source files.
+
+ This function is not meant to be called by the project managers.
+
+ \sa CppTools::CppModelManagerInterface::ProgressNotificationMode
+ \sa CppTools::CppModelManagerInterface::updateProjectInfo()
+*/
+
ProjectPart::ProjectPart()
: cVersion(C89)
, cxxVersion(CXX11)
diff --git a/src/plugins/cpptools/cppmodelmanagerinterface.h b/src/plugins/cpptools/cppmodelmanagerinterface.h
index e4885ea5786..d61020337e8 100644
--- a/src/plugins/cpptools/cppmodelmanagerinterface.h
+++ b/src/plugins/cpptools/cppmodelmanagerinterface.h
@@ -249,6 +249,9 @@ public:
virtual CppTools::CppIndexingSupport *indexingSupport() = 0;
signals:
+ /// Project data might be locked while this is emitted.
+ void aboutToRemoveFiles(const QStringList &files);
+
void documentUpdated(CPlusPlus::Document::Ptr doc);
void sourceFilesRefreshed(const QStringList &files);
@@ -258,9 +261,11 @@ signals:
void projectPartsUpdated(ProjectExplorer::Project *project);
public slots:
- virtual void updateModifiedSourceFiles() = 0;
+ // Documented in source file.
virtual QFuture<void> updateSourceFiles(const QStringList &sourceFiles,
ProgressNotificationMode mode = ReservedProgressNotification) = 0;
+
+ virtual void updateModifiedSourceFiles() = 0;
virtual void GC() = 0;
};
diff --git a/src/plugins/cpptools/cpptoolsplugin.h b/src/plugins/cpptools/cpptoolsplugin.h
index de48a8fe218..70d9dfb6850 100644
--- a/src/plugins/cpptools/cpptoolsplugin.h
+++ b/src/plugins/cpptools/cpptoolsplugin.h
@@ -192,6 +192,9 @@ private slots:
void test_modelmanager_refresh_also_includes_of_project_files();
void test_modelmanager_refresh_several_times();
void test_modelmanager_refresh_test_for_changes();
+ void test_modelmanager_refresh_added_and_purge_removed();
+ void test_modelmanager_refresh_timeStampModified_if_sourcefiles_change();
+ void test_modelmanager_refresh_timeStampModified_if_sourcefiles_change_data();
void test_modelmanager_snapshot_after_two_projects();
void test_modelmanager_extraeditorsupport_uiFiles();
void test_modelmanager_gc_if_last_cppeditor_closed();
diff --git a/tests/cppmodelmanager/testdata_refresh2/source.cpp b/tests/cppmodelmanager/testdata_refresh2/source.cpp
new file mode 100644
index 00000000000..d459c19d5ef
--- /dev/null
+++ b/tests/cppmodelmanager/testdata_refresh2/source.cpp
@@ -0,0 +1 @@
+int someGlobal;
diff --git a/tests/cppmodelmanager/testdata_refresh2/source2.cpp b/tests/cppmodelmanager/testdata_refresh2/source2.cpp
new file mode 100644
index 00000000000..45b14673159
--- /dev/null
+++ b/tests/cppmodelmanager/testdata_refresh2/source2.cpp
@@ -0,0 +1 @@
+int f() {}