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 <QFileDialog>
|
||||||
|
|
||||||
#include <limits>
|
#include <limits>
|
||||||
#include <memory>
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\class ProjectExplorer::Project
|
\class ProjectExplorer::Project
|
||||||
@@ -357,7 +356,8 @@ void Project::setNeedsInitialExpansion(bool needsExpansion)
|
|||||||
d->m_needsInitialExpansion = 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;
|
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!
|
||||||
@@ -372,8 +372,14 @@ void Project::setExtraProjectFiles(const QSet<Utils::FilePath> &projectDocumentP
|
|||||||
return toRemove.contains(d->filePath());
|
return toRemove.contains(d->filePath());
|
||||||
});
|
});
|
||||||
for (const Utils::FilePath &p : toAdd) {
|
for (const Utils::FilePath &p : toAdd) {
|
||||||
d->m_extraProjectDocuments.emplace_back(
|
if (docGenerator) {
|
||||||
std::make_unique<ProjectDocument>(d->m_document->mimeType(), p, this));
|
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);
|
&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)
|
void Project::setProjectLanguages(Core::Context language)
|
||||||
{
|
{
|
||||||
if (d->m_projectLanguages == language)
|
if (d->m_projectLanguages == language)
|
||||||
|
@@ -39,6 +39,7 @@
|
|||||||
#include <QFileSystemModel>
|
#include <QFileSystemModel>
|
||||||
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
namespace Core { class Context; }
|
namespace Core { class Context; }
|
||||||
namespace Utils {
|
namespace Utils {
|
||||||
@@ -123,6 +124,8 @@ public:
|
|||||||
|
|
||||||
Utils::FilePaths files(const NodeMatcher &matcher) const;
|
Utils::FilePaths files(const NodeMatcher &matcher) const;
|
||||||
bool isKnownFile(const Utils::FilePath &filename) const;
|
bool isKnownFile(const Utils::FilePath &filename) const;
|
||||||
|
const Node *nodeForFilePath(const Utils::FilePath &filePath,
|
||||||
|
const NodeMatcher &extraMatcher = {});
|
||||||
|
|
||||||
virtual QVariantMap toMap() const;
|
virtual QVariantMap toMap() const;
|
||||||
|
|
||||||
@@ -159,9 +162,11 @@ public:
|
|||||||
|
|
||||||
void setRootProjectNode(std::unique_ptr<ProjectNode> &&root);
|
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.
|
// 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 setDisplayName(const QString &name);
|
||||||
void setProjectLanguage(Utils::Id id, bool enabled);
|
void setProjectLanguage(Utils::Id id, bool enabled);
|
||||||
|
@@ -63,41 +63,6 @@ using namespace QmakeProjectManager::Internal;
|
|||||||
using namespace QMakeInternal;
|
using namespace QMakeInternal;
|
||||||
using namespace Utils;
|
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 {
|
namespace QmakeProjectManager {
|
||||||
|
|
||||||
static Q_LOGGING_CATEGORY(qmakeParse, "qtc.qmake.parsing", QtWarningMsg);
|
static Q_LOGGING_CATEGORY(qmakeParse, "qtc.qmake.parsing", QtWarningMsg);
|
||||||
|
@@ -33,6 +33,7 @@
|
|||||||
#include "qmakeprojectmanagerconstants.h"
|
#include "qmakeprojectmanagerconstants.h"
|
||||||
#include "qmakestep.h"
|
#include "qmakestep.h"
|
||||||
|
|
||||||
|
#include <coreplugin/documentmanager.h>
|
||||||
#include <coreplugin/editormanager/editormanager.h>
|
#include <coreplugin/editormanager/editormanager.h>
|
||||||
#include <coreplugin/icontext.h>
|
#include <coreplugin/icontext.h>
|
||||||
#include <coreplugin/icore.h>
|
#include <coreplugin/icore.h>
|
||||||
@@ -98,6 +99,38 @@ static Q_LOGGING_CATEGORY(qmakeBuildSystemLog, "qtc.qmake.buildsystem", QtWarnin
|
|||||||
<< msg; \
|
<< 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
|
/// Watches folders for QmakePriFile nodes
|
||||||
/// use one file system watcher to watch all folders
|
/// use one file system watcher to watch all folders
|
||||||
/// such minimizing system ressouce usage
|
/// such minimizing system ressouce usage
|
||||||
@@ -270,8 +303,17 @@ void QmakeBuildSystem::updateDocuments()
|
|||||||
QSet<FilePath> projectDocuments;
|
QSet<FilePath> projectDocuments;
|
||||||
project()->rootProjectNode()->forEachProjectNode([&projectDocuments](const ProjectNode *n) {
|
project()->rootProjectNode()->forEachProjectNode([&projectDocuments](const ProjectNode *n) {
|
||||||
projectDocuments.insert(n->filePath());
|
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()
|
void QmakeBuildSystem::updateCppCodeModel()
|
||||||
|
Reference in New Issue
Block a user