From 4c1c11b7b62ef231a2811d5ae94f7c36716230e0 Mon Sep 17 00:00:00 2001 From: Christian Kandeler Date: Thu, 24 Sep 2020 11:36:10 +0200 Subject: [PATCH] QmakeProjectManager: Fix crash on reparsing After a re-parse, the existing IDocuments need to be updated with the new QmakePriFile object, as the old one may no longer be valid and thus cause a crash on the next re-parse. Amends f3bd07efd1. Fixes: QTCREATORBUG-24683 Change-Id: Ib03d3005cb7831f1e05cb116aa3cdfe6cf5e72ad Reviewed-by: Christian Stenger Reviewed-by: hjk Reviewed-by: Christian Kandeler --- src/plugins/projectexplorer/project.cpp | 7 ++++++- src/plugins/projectexplorer/project.h | 4 +++- .../qmakeprojectmanager/qmakeproject.cpp | 21 ++++++++++++++----- 3 files changed, 25 insertions(+), 7 deletions(-) diff --git a/src/plugins/projectexplorer/project.cpp b/src/plugins/projectexplorer/project.cpp index 1ae6d334709..26ff8183194 100644 --- a/src/plugins/projectexplorer/project.cpp +++ b/src/plugins/projectexplorer/project.cpp @@ -357,7 +357,8 @@ void Project::setNeedsInitialExpansion(bool needsExpansion) } void Project::setExtraProjectFiles(const QSet &projectDocumentPaths, - const DocGenerator docGenerator) + const DocGenerator &docGenerator, + const DocUpdater &docUpdater) { QSet uniqueNewFiles = projectDocumentPaths; uniqueNewFiles.remove(projectFilePath()); // Make sure to never add the main project file! @@ -371,6 +372,10 @@ void Project::setExtraProjectFiles(const QSet &projectDocumentP Utils::erase(d->m_extraProjectDocuments, [&toRemove](const std::unique_ptr &d) { return toRemove.contains(d->filePath()); }); + if (docUpdater) { + for (const auto &doc : qAsConst(d->m_extraProjectDocuments)) + docUpdater(doc.get()); + } for (const Utils::FilePath &p : toAdd) { if (docGenerator) { std::unique_ptr doc = docGenerator(p); diff --git a/src/plugins/projectexplorer/project.h b/src/plugins/projectexplorer/project.h index 42fd4282c5c..64236a39a26 100644 --- a/src/plugins/projectexplorer/project.h +++ b/src/plugins/projectexplorer/project.h @@ -165,8 +165,10 @@ public: // Set project files that will be watched and by default trigger the same callback // as the main project file. using DocGenerator = std::function(const Utils::FilePath &)>; + using DocUpdater = std::function; void setExtraProjectFiles(const QSet &projectDocumentPaths, - const DocGenerator docGenerator = {}); + const DocGenerator &docGenerator = {}, + const DocUpdater &docUpdater = {}); void setDisplayName(const QString &name); void setProjectLanguage(Utils::Id id, bool enabled); diff --git a/src/plugins/qmakeprojectmanager/qmakeproject.cpp b/src/plugins/qmakeprojectmanager/qmakeproject.cpp index 28707f26bb5..043103a2d83 100644 --- a/src/plugins/qmakeprojectmanager/qmakeproject.cpp +++ b/src/plugins/qmakeprojectmanager/qmakeproject.cpp @@ -127,6 +127,8 @@ public: return true; } + void setPriFile(QmakePriFile *priFile) { m_priFile = priFile; } + private: QmakePriFile *m_priFile; }; @@ -305,15 +307,24 @@ void QmakeBuildSystem::updateDocuments() projectDocuments.insert(n->filePath()); }); - project()->setExtraProjectFiles(projectDocuments, [p = project()](const FilePath &fp) - -> std::unique_ptr { + const auto priFileForPath = [p = project()](const FilePath &fp) -> QmakePriFile * { const Node * const n = p->nodeForFilePath(fp, [](const Node *n) { return dynamic_cast(n); }); - QTC_ASSERT(n, return std::make_unique()); - QmakePriFile * const priFile = static_cast(n)->priFile(); + QTC_ASSERT(n, return nullptr); + return static_cast(n)->priFile(); + }; + const auto docGenerator = [&](const FilePath &fp) + -> std::unique_ptr { + QmakePriFile * const priFile = priFileForPath(fp); QTC_ASSERT(priFile, return std::make_unique()); return std::make_unique(priFile, fp); - }); + }; + const auto docUpdater = [&](Core::IDocument *doc) { + QmakePriFile * const priFile = priFileForPath(doc->filePath()); + QTC_ASSERT(priFile, return); + static_cast(doc)->setPriFile(priFile); + }; + project()->setExtraProjectFiles(projectDocuments, docGenerator, docUpdater); } void QmakeBuildSystem::updateCppCodeModel()