From a0d6df7bd85bf88e4ac3643d97d35e04389f6309 Mon Sep 17 00:00:00 2001 From: Erik Verbruggen 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 --- src/libs/cplusplus/CppDocument.cpp | 44 ++++++++++------- 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, 117 insertions(+), 19 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,6 +705,25 @@ Document::Ptr Snapshot::documentFromSource(const QByteArray &preprocessedCode, return newDoc; } +QSet Snapshot::allIncludesForDocument(const QString &fileName) const +{ + QSet result; + allIncludesForDocument_helper(fileName, result); + return result; +} + +void Snapshot::allIncludesForDocument_helper(const QString &fileName, QSet &result) const +{ + if (Document::Ptr doc = document(fileName)) { + foreach (const QString &inc, doc->includedFiles()) { + if (!result.contains(inc)) { + result.insert(inc); + allIncludesForDocument_helper(inc, result); + } + } + } +} + Document::Ptr Snapshot::document(const QString &fileName) const { return _documents.value(fileName); @@ -713,22 +732,13 @@ Document::Ptr Snapshot::document(const QString &fileName) const Snapshot Snapshot::simplified(Document::Ptr doc) const { Snapshot snapshot; - simplified_helper(doc, &snapshot); + + if (doc) { + snapshot.insert(doc); + foreach (const QString &fileName, allIncludesForDocument(doc->fileName())) + if (Document::Ptr inc = document(fileName)) + snapshot.insert(inc); + } + return snapshot; } - -void Snapshot::simplified_helper(Document::Ptr doc, Snapshot *snapshot) const -{ - if (! doc) - return; - - if (! snapshot->contains(doc->fileName())) { - snapshot->insert(doc); - - foreach (const Document::Include &incl, doc->includes()) { - Document::Ptr includedDoc = document(incl.fileName()); - simplified_helper(includedDoc, 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 allIncludesForDocument(const QString &fileName) const; + private: - void simplified_helper(Document::Ptr doc, Snapshot *snapshot) const; + void allIncludesForDocument_helper(const QString &fileName, QSet &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