forked from qt-creator/qt-creator
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 <christian.stenger@qt.io>
Reviewed-by: hjk <hjk@qt.io>
Reviewed-by: Christian Kandeler <christian.kandeler@qt.io>
This commit is contained in:
@@ -357,7 +357,8 @@ void Project::setNeedsInitialExpansion(bool needsExpansion)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Project::setExtraProjectFiles(const QSet<Utils::FilePath> &projectDocumentPaths,
|
void Project::setExtraProjectFiles(const QSet<Utils::FilePath> &projectDocumentPaths,
|
||||||
const DocGenerator docGenerator)
|
const DocGenerator &docGenerator,
|
||||||
|
const DocUpdater &docUpdater)
|
||||||
{
|
{
|
||||||
QSet<Utils::FilePath> uniqueNewFiles = projectDocumentPaths;
|
QSet<Utils::FilePath> uniqueNewFiles = projectDocumentPaths;
|
||||||
uniqueNewFiles.remove(projectFilePath()); // Make sure to never add the main project file!
|
uniqueNewFiles.remove(projectFilePath()); // Make sure to never add the main project file!
|
||||||
@@ -371,6 +372,10 @@ void Project::setExtraProjectFiles(const QSet<Utils::FilePath> &projectDocumentP
|
|||||||
Utils::erase(d->m_extraProjectDocuments, [&toRemove](const std::unique_ptr<Core::IDocument> &d) {
|
Utils::erase(d->m_extraProjectDocuments, [&toRemove](const std::unique_ptr<Core::IDocument> &d) {
|
||||||
return toRemove.contains(d->filePath());
|
return toRemove.contains(d->filePath());
|
||||||
});
|
});
|
||||||
|
if (docUpdater) {
|
||||||
|
for (const auto &doc : qAsConst(d->m_extraProjectDocuments))
|
||||||
|
docUpdater(doc.get());
|
||||||
|
}
|
||||||
for (const Utils::FilePath &p : toAdd) {
|
for (const Utils::FilePath &p : toAdd) {
|
||||||
if (docGenerator) {
|
if (docGenerator) {
|
||||||
std::unique_ptr<Core::IDocument> doc = docGenerator(p);
|
std::unique_ptr<Core::IDocument> doc = docGenerator(p);
|
||||||
|
@@ -165,8 +165,10 @@ public:
|
|||||||
// Set project files that will be watched and by default trigger the same callback
|
// Set project files that will be watched and by default trigger the same callback
|
||||||
// as the main project file.
|
// as the main project file.
|
||||||
using DocGenerator = std::function<std::unique_ptr<Core::IDocument>(const Utils::FilePath &)>;
|
using DocGenerator = std::function<std::unique_ptr<Core::IDocument>(const Utils::FilePath &)>;
|
||||||
|
using DocUpdater = std::function<void(Core::IDocument *)>;
|
||||||
void setExtraProjectFiles(const QSet<Utils::FilePath> &projectDocumentPaths,
|
void setExtraProjectFiles(const QSet<Utils::FilePath> &projectDocumentPaths,
|
||||||
const DocGenerator docGenerator = {});
|
const DocGenerator &docGenerator = {},
|
||||||
|
const DocUpdater &docUpdater = {});
|
||||||
|
|
||||||
void setDisplayName(const QString &name);
|
void setDisplayName(const QString &name);
|
||||||
void setProjectLanguage(Utils::Id id, bool enabled);
|
void setProjectLanguage(Utils::Id id, bool enabled);
|
||||||
|
@@ -127,6 +127,8 @@ public:
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void setPriFile(QmakePriFile *priFile) { m_priFile = priFile; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QmakePriFile *m_priFile;
|
QmakePriFile *m_priFile;
|
||||||
};
|
};
|
||||||
@@ -305,15 +307,24 @@ void QmakeBuildSystem::updateDocuments()
|
|||||||
projectDocuments.insert(n->filePath());
|
projectDocuments.insert(n->filePath());
|
||||||
|
|
||||||
});
|
});
|
||||||
project()->setExtraProjectFiles(projectDocuments, [p = project()](const FilePath &fp)
|
const auto priFileForPath = [p = project()](const FilePath &fp) -> QmakePriFile * {
|
||||||
-> std::unique_ptr<Core::IDocument> {
|
|
||||||
const Node * const n = p->nodeForFilePath(fp, [](const Node *n) {
|
const Node * const n = p->nodeForFilePath(fp, [](const Node *n) {
|
||||||
return dynamic_cast<const QmakePriFileNode *>(n); });
|
return dynamic_cast<const QmakePriFileNode *>(n); });
|
||||||
QTC_ASSERT(n, return std::make_unique<Core::IDocument>());
|
QTC_ASSERT(n, return nullptr);
|
||||||
QmakePriFile * const priFile = static_cast<const QmakePriFileNode *>(n)->priFile();
|
return static_cast<const QmakePriFileNode *>(n)->priFile();
|
||||||
|
};
|
||||||
|
const auto docGenerator = [&](const FilePath &fp)
|
||||||
|
-> std::unique_ptr<Core::IDocument> {
|
||||||
|
QmakePriFile * const priFile = priFileForPath(fp);
|
||||||
QTC_ASSERT(priFile, return std::make_unique<Core::IDocument>());
|
QTC_ASSERT(priFile, return std::make_unique<Core::IDocument>());
|
||||||
return std::make_unique<QmakePriFileDocument>(priFile, fp);
|
return std::make_unique<QmakePriFileDocument>(priFile, fp);
|
||||||
});
|
};
|
||||||
|
const auto docUpdater = [&](Core::IDocument *doc) {
|
||||||
|
QmakePriFile * const priFile = priFileForPath(doc->filePath());
|
||||||
|
QTC_ASSERT(priFile, return);
|
||||||
|
static_cast<QmakePriFileDocument *>(doc)->setPriFile(priFile);
|
||||||
|
};
|
||||||
|
project()->setExtraProjectFiles(projectDocuments, docGenerator, docUpdater);
|
||||||
}
|
}
|
||||||
|
|
||||||
void QmakeBuildSystem::updateCppCodeModel()
|
void QmakeBuildSystem::updateCppCodeModel()
|
||||||
|
Reference in New Issue
Block a user