From a0d6df7bd85bf88e4ac3643d97d35e04389f6309 Mon Sep 17 00:00:00 2001 From: Erik Verbruggen <erik.verbruggen@digia.com> Date: Thu, 11 Apr 2013 12:51:06 +0200 Subject: [PATCH] C++: also refresh files not in the project when project changes. System headers and other file which are not explicitly mentioned in the project must be reparsed when the project changes. Task-number: QTCREATORBUG-9056 Change-Id: I32f1206d241a078a4d9b15fac5813f365a1ba303 Reviewed-by: Nikolai Kosjar <nikolai.kosjar@digia.com> --- src/libs/cplusplus/CppDocument.cpp | 42 +++++++++------- src/libs/cplusplus/CppDocument.h | 4 +- src/plugins/cpptools/cppmodelmanager.cpp | 8 +++- src/plugins/cpptools/cppmodelmanager_test.cpp | 48 +++++++++++++++++++ src/plugins/cpptools/cpptoolsplugin.h | 1 + .../cpptools/modelmanagertesthelper.cpp | 17 +++++++ src/plugins/cpptools/modelmanagertesthelper.h | 9 ++++ .../sources/test_modelmanager_refresh.cpp | 1 + .../sources/test_modelmanager_refresh.h | 4 ++ 9 files changed, 116 insertions(+), 18 deletions(-) create mode 100644 tests/cppmodelmanager/testdata/sources/test_modelmanager_refresh.cpp create mode 100644 tests/cppmodelmanager/testdata/sources/test_modelmanager_refresh.h diff --git a/src/libs/cplusplus/CppDocument.cpp b/src/libs/cplusplus/CppDocument.cpp index 2385238b9c7..13c0b3f6ad8 100644 --- a/src/libs/cplusplus/CppDocument.cpp +++ b/src/libs/cplusplus/CppDocument.cpp @@ -705,30 +705,40 @@ Document::Ptr Snapshot::documentFromSource(const QByteArray &preprocessedCode, return newDoc; } -Document::Ptr Snapshot::document(const QString &fileName) const +QSet<QString> Snapshot::allIncludesForDocument(const QString &fileName) const { - return _documents.value(fileName); + QSet<QString> result; + allIncludesForDocument_helper(fileName, result); + return result; } -Snapshot Snapshot::simplified(Document::Ptr doc) const +void Snapshot::allIncludesForDocument_helper(const QString &fileName, QSet<QString> &result) const { - Snapshot snapshot; - simplified_helper(doc, &snapshot); - return snapshot; + if (Document::Ptr doc = document(fileName)) { + foreach (const QString &inc, doc->includedFiles()) { + if (!result.contains(inc)) { + result.insert(inc); + allIncludesForDocument_helper(inc, result); + } + } + } } -void Snapshot::simplified_helper(Document::Ptr doc, Snapshot *snapshot) const +Document::Ptr Snapshot::document(const QString &fileName) const { - if (! doc) - return; + return _documents.value(fileName); +} - if (! snapshot->contains(doc->fileName())) { - snapshot->insert(doc); +Snapshot Snapshot::simplified(Document::Ptr doc) const +{ + Snapshot snapshot; - foreach (const Document::Include &incl, doc->includes()) { - Document::Ptr includedDoc = document(incl.fileName()); - simplified_helper(includedDoc, snapshot); - } + if (doc) { + snapshot.insert(doc); + foreach (const QString &fileName, allIncludesForDocument(doc->fileName())) + if (Document::Ptr inc = document(fileName)) + snapshot.insert(inc); } -} + return snapshot; +} diff --git a/src/libs/cplusplus/CppDocument.h b/src/libs/cplusplus/CppDocument.h index 9d2cd128e21..589e2b9503a 100644 --- a/src/libs/cplusplus/CppDocument.h +++ b/src/libs/cplusplus/CppDocument.h @@ -389,8 +389,10 @@ public: Document::Ptr documentFromSource(const QByteArray &preprocessedDocument, const QString &fileName) const; + QSet<QString> allIncludesForDocument(const QString &fileName) const; + private: - void simplified_helper(Document::Ptr doc, Snapshot *snapshot) const; + void allIncludesForDocument_helper(const QString &fileName, QSet<QString> &result) const; private: _Base _documents; diff --git a/src/plugins/cpptools/cppmodelmanager.cpp b/src/plugins/cpptools/cppmodelmanager.cpp index e382171c398..cef667fec0e 100644 --- a/src/plugins/cpptools/cppmodelmanager.cpp +++ b/src/plugins/cpptools/cppmodelmanager.cpp @@ -970,10 +970,16 @@ void CppModelManager::updateProjectInfo(const ProjectInfo &pinfo) foreach (const ProjectInfo &projectInfo, m_projects) { foreach (const ProjectPart::Ptr &projectPart, projectInfo.projectParts()) { - foreach (const ProjectFile &cxxFile, projectPart->files) + foreach (const ProjectFile &cxxFile, projectPart->files) { m_srcToProjectPart[cxxFile.path].append(projectPart); + foreach (const QString &fileName, m_snapshot.allIncludesForDocument(cxxFile.path)) + m_snapshot.remove(fileName); + m_snapshot.remove(cxxFile.path); + } } } + + m_snapshot.remove(configurationFileName()); } if (!qgetenv("QTCREATOR_DUMP_PROJECT_INFO").isEmpty()) diff --git a/src/plugins/cpptools/cppmodelmanager_test.cpp b/src/plugins/cpptools/cppmodelmanager_test.cpp index 4525b95a35f..2a9462674f4 100644 --- a/src/plugins/cpptools/cppmodelmanager_test.cpp +++ b/src/plugins/cpptools/cppmodelmanager_test.cpp @@ -138,3 +138,51 @@ void CppToolsPlugin::test_modelmanager_framework_headers() QVERIFY(chars.startsWith("success")); } } + +/// QTCREATORBUG-9056 +void CppToolsPlugin::test_modelmanager_refresh() +{ + ModelManagerTestHelper helper; + CppModelManager *mm = CppModelManager::instance(); + + const QString testCpp(testSource(QLatin1String("test_modelmanager_refresh.cpp"))); + const QString testHeader(testSource(QLatin1String("test_modelmanager_refresh.h"))); + + Project *project = helper.createProject(QLatin1String("test_modelmanager_refresh")); + ProjectInfo pi = mm->projectInfo(project); + QCOMPARE(pi.project().data(), project); + + ProjectPart::Ptr part(new ProjectPart); + pi.appendProjectPart(part); + part->cxxVersion = ProjectPart::CXX98; + part->qtVersion = ProjectPart::Qt5; + part->defines = QByteArray("#define OH_BEHAVE -1\n"); + part->includePaths = QStringList() << testIncludeDir(false); + part->files.append(ProjectFile(testCpp, ProjectFile::CXXSource)); + + mm->updateProjectInfo(pi); + mm->updateSourceFiles(QStringList() << testCpp); + + QStringList refreshedFiles = helper.waitForRefreshedSourceFiles(); + + QCOMPARE(refreshedFiles.size(), 1); + QVERIFY(refreshedFiles.contains(testCpp)); + CPlusPlus::Snapshot snapshot = mm->snapshot(); + QVERIFY(snapshot.contains(testHeader)); + QVERIFY(snapshot.contains(testCpp)); + + part->defines = QByteArray(); + mm->updateProjectInfo(pi); + snapshot = mm->snapshot(); + QVERIFY(!snapshot.contains(testHeader)); + QVERIFY(!snapshot.contains(testCpp)); + + mm->updateSourceFiles(QStringList() << testCpp); + refreshedFiles = helper.waitForRefreshedSourceFiles(); + + QCOMPARE(refreshedFiles.size(), 1); + QVERIFY(refreshedFiles.contains(testCpp)); + snapshot = mm->snapshot(); + QVERIFY(snapshot.contains(testHeader)); + QVERIFY(snapshot.contains(testCpp)); +} diff --git a/src/plugins/cpptools/cpptoolsplugin.h b/src/plugins/cpptools/cpptoolsplugin.h index 4e6ead7b0a9..dfce31798ab 100644 --- a/src/plugins/cpptools/cpptoolsplugin.h +++ b/src/plugins/cpptools/cpptoolsplugin.h @@ -137,6 +137,7 @@ private slots: void test_modelmanager_paths(); void test_modelmanager_framework_headers(); + void test_modelmanager_refresh(); private: void test_completion(); diff --git a/src/plugins/cpptools/modelmanagertesthelper.cpp b/src/plugins/cpptools/modelmanagertesthelper.cpp index 54dc946bbad..46f2a917239 100644 --- a/src/plugins/cpptools/modelmanagertesthelper.cpp +++ b/src/plugins/cpptools/modelmanagertesthelper.cpp @@ -54,6 +54,7 @@ ModelManagerTestHelper::ModelManagerTestHelper(QObject *parent) : connect(this, SIGNAL(aboutToRemoveProject(ProjectExplorer::Project*)), mm, SLOT(onAboutToRemoveProject(ProjectExplorer::Project*))); connect(this, SIGNAL(projectAdded(ProjectExplorer::Project*)), mm, SLOT(onProjectAdded(ProjectExplorer::Project*))); + connect(mm, SIGNAL(sourceFilesRefreshed(QStringList)), this, SLOT(sourceFilesRefreshed(QStringList))); cleanup(); verifyClean(); @@ -97,3 +98,19 @@ ModelManagerTestHelper::Project *ModelManagerTestHelper::createProject(const QSt return tp; } +QStringList ModelManagerTestHelper::waitForRefreshedSourceFiles() +{ + m_refreshHappened = false; + + while (!m_refreshHappened) + QCoreApplication::processEvents(); + + return m_lastRefreshedSourceFiles; +} + + +void ModelManagerTestHelper::sourceFilesRefreshed(const QStringList &files) +{ + m_lastRefreshedSourceFiles = files; + m_refreshHappened = true; +} diff --git a/src/plugins/cpptools/modelmanagertesthelper.h b/src/plugins/cpptools/modelmanagertesthelper.h index ade58b32f64..8a228cac42a 100644 --- a/src/plugins/cpptools/modelmanagertesthelper.h +++ b/src/plugins/cpptools/modelmanagertesthelper.h @@ -83,9 +83,18 @@ public: Project *createProject(const QString &name); + QStringList waitForRefreshedSourceFiles(); + signals: void aboutToRemoveProject(ProjectExplorer::Project *project); void projectAdded(ProjectExplorer::Project*); + +public slots: + void sourceFilesRefreshed(const QStringList &files); + +private: + bool m_refreshHappened; + QStringList m_lastRefreshedSourceFiles; }; } // namespace Internal diff --git a/tests/cppmodelmanager/testdata/sources/test_modelmanager_refresh.cpp b/tests/cppmodelmanager/testdata/sources/test_modelmanager_refresh.cpp new file mode 100644 index 00000000000..ad92e705f6f --- /dev/null +++ b/tests/cppmodelmanager/testdata/sources/test_modelmanager_refresh.cpp @@ -0,0 +1 @@ +#include "test_modelmanager_refresh.h" diff --git a/tests/cppmodelmanager/testdata/sources/test_modelmanager_refresh.h b/tests/cppmodelmanager/testdata/sources/test_modelmanager_refresh.h new file mode 100644 index 00000000000..43bcd865776 --- /dev/null +++ b/tests/cppmodelmanager/testdata/sources/test_modelmanager_refresh.h @@ -0,0 +1,4 @@ +#ifndef test_modelmanager_refresh_h +#define test_modelmanager_refresh_h + +#endif // test_modelmanager_refresh_h -- GitLab