forked from qt-creator/qt-creator
QmakeProjectManager: Restore incremental re-parsing
This was broken in commit 37aecdd112
, where we overlooked that a special
type of IDocument was used that triggers a re-parse of only the affected
part of the project tree. As a result, all changes to a .pri or .pro file
would trigger a re-parse of the entire project.
Fixes: QTCREATORBUG-24572
Change-Id: I480cff4e53cf86a17e1eaac0eb9b32901bc87051
Reviewed-by: hjk <hjk@qt.io>
This commit is contained in:
@@ -64,7 +64,6 @@
|
||||
#include <QFileDialog>
|
||||
|
||||
#include <limits>
|
||||
#include <memory>
|
||||
|
||||
/*!
|
||||
\class ProjectExplorer::Project
|
||||
@@ -357,7 +356,8 @@ void Project::setNeedsInitialExpansion(bool needsExpansion)
|
||||
d->m_needsInitialExpansion = needsExpansion;
|
||||
}
|
||||
|
||||
void Project::setExtraProjectFiles(const QSet<Utils::FilePath> &projectDocumentPaths)
|
||||
void Project::setExtraProjectFiles(const QSet<Utils::FilePath> &projectDocumentPaths,
|
||||
const DocGenerator docGenerator)
|
||||
{
|
||||
QSet<Utils::FilePath> uniqueNewFiles = projectDocumentPaths;
|
||||
uniqueNewFiles.remove(projectFilePath()); // Make sure to never add the main project file!
|
||||
@@ -372,8 +372,14 @@ void Project::setExtraProjectFiles(const QSet<Utils::FilePath> &projectDocumentP
|
||||
return toRemove.contains(d->filePath());
|
||||
});
|
||||
for (const Utils::FilePath &p : toAdd) {
|
||||
d->m_extraProjectDocuments.emplace_back(
|
||||
std::make_unique<ProjectDocument>(d->m_document->mimeType(), p, this));
|
||||
if (docGenerator) {
|
||||
std::unique_ptr<Core::IDocument> doc = docGenerator(p);
|
||||
QTC_ASSERT(doc, continue);
|
||||
d->m_extraProjectDocuments.push_back(std::move(doc));
|
||||
} else {
|
||||
d->m_extraProjectDocuments.emplace_back(std::make_unique<ProjectDocument>(
|
||||
d->m_document->mimeType(), p, this));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -802,6 +808,19 @@ bool Project::isKnownFile(const Utils::FilePath &filename) const
|
||||
&element, nodeLessThan);
|
||||
}
|
||||
|
||||
const Node *Project::nodeForFilePath(const Utils::FilePath &filePath,
|
||||
const Project::NodeMatcher &extraMatcher)
|
||||
{
|
||||
const FileNode dummy(filePath, FileType::Unknown);
|
||||
const auto range = std::equal_range(d->m_sortedNodeList.cbegin(), d->m_sortedNodeList.cend(),
|
||||
&dummy, &nodeLessThan);
|
||||
for (auto it = range.first; it != range.second; ++it) {
|
||||
if ((*it)->filePath() == filePath && (!extraMatcher || extraMatcher(*it)))
|
||||
return *it;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void Project::setProjectLanguages(Core::Context language)
|
||||
{
|
||||
if (d->m_projectLanguages == language)
|
||||
|
@@ -39,6 +39,7 @@
|
||||
#include <QFileSystemModel>
|
||||
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
|
||||
namespace Core { class Context; }
|
||||
namespace Utils {
|
||||
@@ -123,6 +124,8 @@ public:
|
||||
|
||||
Utils::FilePaths files(const NodeMatcher &matcher) const;
|
||||
bool isKnownFile(const Utils::FilePath &filename) const;
|
||||
const Node *nodeForFilePath(const Utils::FilePath &filePath,
|
||||
const NodeMatcher &extraMatcher = {});
|
||||
|
||||
virtual QVariantMap toMap() const;
|
||||
|
||||
@@ -159,9 +162,11 @@ public:
|
||||
|
||||
void setRootProjectNode(std::unique_ptr<ProjectNode> &&root);
|
||||
|
||||
// Set project files that will be watched and trigger the same callback
|
||||
// Set project files that will be watched and by default trigger the same callback
|
||||
// as the main project file.
|
||||
void setExtraProjectFiles(const QSet<Utils::FilePath> &projectDocumentPaths);
|
||||
using DocGenerator = std::function<std::unique_ptr<Core::IDocument>(const Utils::FilePath &)>;
|
||||
void setExtraProjectFiles(const QSet<Utils::FilePath> &projectDocumentPaths,
|
||||
const DocGenerator docGenerator = {});
|
||||
|
||||
void setDisplayName(const QString &name);
|
||||
void setProjectLanguage(Utils::Id id, bool enabled);
|
||||
|
@@ -63,41 +63,6 @@ using namespace QmakeProjectManager::Internal;
|
||||
using namespace QMakeInternal;
|
||||
using namespace Utils;
|
||||
|
||||
namespace {
|
||||
|
||||
class QmakePriFileDocument : public Core::IDocument
|
||||
{
|
||||
public:
|
||||
QmakePriFileDocument(QmakePriFile *qmakePriFile, const Utils::FilePath &filePath) :
|
||||
IDocument(nullptr), m_priFile(qmakePriFile)
|
||||
{
|
||||
setId("Qmake.PriFile");
|
||||
setMimeType(QLatin1String(QmakeProjectManager::Constants::PROFILE_MIMETYPE));
|
||||
setFilePath(filePath);
|
||||
}
|
||||
|
||||
ReloadBehavior reloadBehavior(ChangeTrigger state, ChangeType type) const override
|
||||
{
|
||||
Q_UNUSED(state)
|
||||
Q_UNUSED(type)
|
||||
return BehaviorSilent;
|
||||
}
|
||||
bool reload(QString *errorString, ReloadFlag flag, ChangeType type) override
|
||||
{
|
||||
Q_UNUSED(errorString)
|
||||
Q_UNUSED(flag)
|
||||
if (type == TypePermissions)
|
||||
return true;
|
||||
m_priFile->scheduleUpdate();
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
QmakePriFile *m_priFile;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace QmakeProjectManager {
|
||||
|
||||
static Q_LOGGING_CATEGORY(qmakeParse, "qtc.qmake.parsing", QtWarningMsg);
|
||||
|
@@ -33,6 +33,7 @@
|
||||
#include "qmakeprojectmanagerconstants.h"
|
||||
#include "qmakestep.h"
|
||||
|
||||
#include <coreplugin/documentmanager.h>
|
||||
#include <coreplugin/editormanager/editormanager.h>
|
||||
#include <coreplugin/icontext.h>
|
||||
#include <coreplugin/icore.h>
|
||||
@@ -98,6 +99,38 @@ static Q_LOGGING_CATEGORY(qmakeBuildSystemLog, "qtc.qmake.buildsystem", QtWarnin
|
||||
<< msg; \
|
||||
}
|
||||
|
||||
class QmakePriFileDocument : public Core::IDocument
|
||||
{
|
||||
public:
|
||||
QmakePriFileDocument(QmakePriFile *qmakePriFile, const Utils::FilePath &filePath) :
|
||||
IDocument(nullptr), m_priFile(qmakePriFile)
|
||||
{
|
||||
setId("Qmake.PriFile");
|
||||
setMimeType(QLatin1String(QmakeProjectManager::Constants::PROFILE_MIMETYPE));
|
||||
setFilePath(filePath);
|
||||
Core::DocumentManager::addDocument(this);
|
||||
}
|
||||
|
||||
ReloadBehavior reloadBehavior(ChangeTrigger state, ChangeType type) const override
|
||||
{
|
||||
Q_UNUSED(state)
|
||||
Q_UNUSED(type)
|
||||
return BehaviorSilent;
|
||||
}
|
||||
bool reload(QString *errorString, ReloadFlag flag, ChangeType type) override
|
||||
{
|
||||
Q_UNUSED(errorString)
|
||||
Q_UNUSED(flag)
|
||||
if (type == TypePermissions)
|
||||
return true;
|
||||
m_priFile->scheduleUpdate();
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
QmakePriFile *m_priFile;
|
||||
};
|
||||
|
||||
/// Watches folders for QmakePriFile nodes
|
||||
/// use one file system watcher to watch all folders
|
||||
/// such minimizing system ressouce usage
|
||||
@@ -270,8 +303,17 @@ void QmakeBuildSystem::updateDocuments()
|
||||
QSet<FilePath> projectDocuments;
|
||||
project()->rootProjectNode()->forEachProjectNode([&projectDocuments](const ProjectNode *n) {
|
||||
projectDocuments.insert(n->filePath());
|
||||
|
||||
});
|
||||
project()->setExtraProjectFiles(projectDocuments, [p = project()](const FilePath &fp)
|
||||
-> std::unique_ptr<Core::IDocument> {
|
||||
const Node * const n = p->nodeForFilePath(fp, [](const Node *n) {
|
||||
return dynamic_cast<const QmakePriFileNode *>(n); });
|
||||
QTC_ASSERT(n, return std::make_unique<Core::IDocument>());
|
||||
QmakePriFile * const priFile = static_cast<const QmakePriFileNode *>(n)->priFile();
|
||||
QTC_ASSERT(priFile, return std::make_unique<Core::IDocument>());
|
||||
return std::make_unique<QmakePriFileDocument>(priFile, fp);
|
||||
});
|
||||
project()->setExtraProjectFiles(projectDocuments);
|
||||
}
|
||||
|
||||
void QmakeBuildSystem::updateCppCodeModel()
|
||||
|
Reference in New Issue
Block a user