ProjectExplorer: Slim down user side ProjectNode handling

Change-Id: If727ff6cd09cc127e031c49c47f61ffda631a80e
Reviewed-by: Tobias Hunger <tobias.hunger@qt.io>
This commit is contained in:
hjk
2017-01-26 11:58:57 +01:00
parent cd70da5dcd
commit beaba559a5
8 changed files with 46 additions and 148 deletions

View File

@@ -33,6 +33,7 @@
#include "cmakeprojectconstants.h"
#include "cmakebuildsettingswidget.h"
#include "cmakeprojectmanager.h"
#include "cmakeprojectnodes.h"
#include <coreplugin/documentmanager.h>
#include <coreplugin/icore.h>
@@ -216,6 +217,9 @@ void CMakeBuildConfiguration::generateProjectTree(CMakeListsNode *root,
if (!m_buildDirManager || m_buildDirManager->isParsing())
return;
root->removeProjectNodes();
root->setFolderNodes({});
root->setFileNodes({});
m_buildDirManager->generateProjectTree(root, allFiles);
}

View File

@@ -250,11 +250,11 @@ static ProjectNode *updateCMakeInputs(CMakeListsNode *root,
if (!cmakeVFolder) {
if (hasInputs) {
cmakeVFolder = new CMakeInputsNode(root->filePath());
root->addProjectNodes({ cmakeVFolder });
root->addProjectNode(cmakeVFolder);
}
} else {
if (!hasInputs)
root->removeProjectNodes({ cmakeVFolder });
root->removeProjectNode(cmakeVFolder);
}
if (!hasInputs)
return nullptr;
@@ -304,15 +304,11 @@ void ServerModeReader::generateProjectTree(CMakeListsNode *root,
if (!m_projects.isEmpty())
root->setDisplayName(m_projects.at(0)->name);
QSet<Node *> usedNodes;
usedNodes.insert(updateCMakeInputs(root, m_parameters.sourceDirectory, m_parameters.buildDirectory,
cmakeFilesSource, cmakeFilesBuild, cmakeFilesOther));
updateCMakeInputs(root, m_parameters.sourceDirectory, m_parameters.buildDirectory,
cmakeFilesSource, cmakeFilesBuild, cmakeFilesOther);
usedNodes.unite(updateCMakeLists(root, cmakeLists));
usedNodes.unite(updateProjects(root, m_projects, allFiles));
// Trim out unused nodes:
root->trim(usedNodes);
updateCMakeLists(root, cmakeLists);
updateProjects(root, m_projects, allFiles);
}
QSet<Core::Id> ServerModeReader::updateCodeModel(CppTools::ProjectPartBuilder &ppBuilder)
@@ -583,7 +579,7 @@ QSet<Node *> ServerModeReader::updateCMakeLists(CMakeListsNode *root,
cmln = static_cast<CMakeListsNode *>(parentNode->projectNode(fn->filePath()));
if (!cmln) {
cmln = new CMakeListsNode(fn->filePath());
parentNode->addProjectNodes({ cmln });
parentNode->addProjectNode(cmln);
}
// Find or create CMakeLists.txt filenode below CMakeListsNode:
@@ -647,7 +643,7 @@ static CMakeProjectNode *findOrCreateProjectNode(CMakeListsNode *root, const Uti
CMakeProjectNode *pn = static_cast<CMakeProjectNode *>(cmln->projectNode(projectName));
if (!pn) {
pn = new CMakeProjectNode(projectName);
cmln->addProjectNodes({ pn });
cmln->addProjectNode(pn);
}
pn->setDisplayName(displayName);
return pn;
@@ -688,7 +684,7 @@ static CMakeTargetNode *findOrCreateTargetNode(CMakeListsNode *root, const Utils
CMakeTargetNode *tn = static_cast<CMakeTargetNode *>(cmln->projectNode(targetName));
if (!tn) {
tn = new CMakeTargetNode(targetName);
cmln->addProjectNodes({ tn });
cmln->addProjectNode(tn);
}
tn->setDisplayName(displayName);
return tn;

View File

@@ -243,20 +243,6 @@ CMakeConfig TeaLeafReader::takeParsedConfiguration()
return result;
}
static void sanitizeTree(CMakeListsNode *root)
{
QSet<FileName> uniqueFileNames;
QSet<Node *> uniqueNodes;
foreach (FileNode *fn, root->recursiveFileNodes()) {
const int count = uniqueFileNames.count();
uniqueFileNames.insert(fn->filePath());
if (count != uniqueFileNames.count())
uniqueNodes.insert(static_cast<Node *>(fn));
}
root->trim(uniqueNodes);
root->removeProjectNodes(root->projectNodes()); // Remove all project nodes
}
void TeaLeafReader::generateProjectTree(CMakeListsNode *root, const QList<const FileNode *> &allFiles)
{
root->setDisplayName(m_projectName);
@@ -308,7 +294,6 @@ void TeaLeafReader::generateProjectTree(CMakeListsNode *root, const QList<const
QList<FileNode *> fileNodes = m_files + Utils::transform(missingHeaders, [](const FileNode *fn) { return new FileNode(*fn); });
sanitizeTree(root); // Filter out duplicate nodes that e.g. the servermode reader introduces:
root->buildTree(fileNodes, m_parameters.sourceDirectory);
m_files.clear(); // Some of the FileNodes in files() were deleted!
}

View File

@@ -185,11 +185,6 @@ void Node::emitTreeChanged()
ProjectTree::emitDataChanged();
}
Node *Node::trim(const QSet<Node *> &keepers)
{
return keepers.contains(this) ? nullptr : this;
}
bool Node::sortByPath(const Node *a, const Node *b)
{
return a->filePath() < b->filePath();
@@ -339,26 +334,6 @@ QIcon FolderNode::icon() const
return m_icon;
}
Node *FolderNode::trim(const QSet<Node *> &keepers)
{
if (keepers.contains(this))
return nullptr;
bool keepThis = false;
QList<Node *> toTrim = Utils::transform(m_fileNodes, [&keepers](Node *n) { return n->trim(keepers); });
int count = toTrim.count();
toTrim = Utils::filtered(toTrim, [](const Node *n) { return n; });
keepThis = (count != toTrim.count());
removeFileNodes(Utils::transform(toTrim, [](Node *n) { return static_cast<FileNode *>(n); }));
toTrim = Utils::transform(m_folderNodes, [&keepers](Node *n) { return n->trim(keepers); });
count = toTrim.count();
toTrim = Utils::filtered(toTrim, [](const Node *n) { return n; });
keepThis = keepThis || (count != toTrim.count());
removeFolderNodes(Utils::transform(toTrim, [](Node *n) { return static_cast<FolderNode *>(n); }));
return keepThis ? nullptr : this;
}
QList<FileNode*> FolderNode::fileNodes() const
{
return m_fileNodes;
@@ -829,25 +804,19 @@ QList<ProjectNode*> ProjectNode::projectNodes() const
Adds project nodes specified by \a subProjects to the node hierarchy and
emits the corresponding signals.
*/
void ProjectNode::addProjectNodes(const QList<ProjectNode*> &subProjects)
void ProjectNode::addProjectNode(ProjectNode *subProject)
{
if (!subProjects.isEmpty()) {
QList<FolderNode*> folderNodes;
foreach (ProjectNode *projectNode, subProjects)
folderNodes << projectNode;
QTC_ASSERT(subProject, return);
QTC_ASSERT(!subProject->parentFolderNode(), return);
foreach (ProjectNode *project, subProjects) {
QTC_ASSERT(!project->parentFolderNode() || project->parentFolderNode() == this,
qDebug("Project node has already a parent"));
project->setParentFolderNode(this);
m_folderNodes.append(project);
m_projectNodes.append(project);
}
subProject->setParentFolderNode(this);
m_folderNodes.append(subProject);
m_projectNodes.append(subProject);
Utils::sort(m_folderNodes);
Utils::sort(m_projectNodes);
}
}
/*!
Removes project nodes specified by \a subProjects from the node hierarchy
@@ -856,50 +825,20 @@ void ProjectNode::addProjectNodes(const QList<ProjectNode*> &subProjects)
All objects in the \a subProjects list are deleted.
*/
void ProjectNode::removeProjectNodes(const QList<ProjectNode*> &subProjects)
void ProjectNode::removeProjectNodes()
{
if (!subProjects.isEmpty()) {
QList<FolderNode*> toRemove;
foreach (ProjectNode *projectNode, subProjects)
toRemove << projectNode;
Utils::sort(toRemove);
foreach (ProjectNode *subProject, m_projectNodes)
m_folderNodes.removeAll(subProject);
auto toRemoveIter = toRemove.constBegin();
auto folderIter = m_folderNodes.begin();
auto projectIter = m_projectNodes.begin();
for (; toRemoveIter != toRemove.constEnd(); ++toRemoveIter) {
while (*projectIter != *toRemoveIter) {
++projectIter;
QTC_ASSERT(projectIter != m_projectNodes.end(),
qDebug("Project to remove is not part of specified folder!"));
}
while (*folderIter != *toRemoveIter) {
++folderIter;
QTC_ASSERT(folderIter != m_folderNodes.end(),
qDebug("Project to remove is not part of specified folder!"));
}
delete *projectIter;
projectIter = m_projectNodes.erase(projectIter);
folderIter = m_folderNodes.erase(folderIter);
}
}
qDeleteAll(m_projectNodes);
m_projectNodes.clear();
}
Node *ProjectNode::trim(const QSet<Node *> &keepers)
void ProjectNode::removeProjectNode(ProjectNode *subProject)
{
if (keepers.contains(this))
return nullptr;
QList<Node *> toTrim
= Utils::transform(m_projectNodes, [&keepers](Node *n) { return n->trim(keepers); });
int count = toTrim.count();
toTrim = Utils::filtered(toTrim, [](Node *n) { return n; });
removeProjectNodes(Utils::transform(toTrim, [](Node *n) { return static_cast<ProjectNode *>(n); }));
if (!FolderNode::trim(keepers))
return nullptr;
return (toTrim.count() != count) ? nullptr : this;
m_projectNodes.removeOne(subProject);
m_folderNodes.removeOne(subProject);
delete subProject;
}
/*!

View File

@@ -144,8 +144,6 @@ public:
void emitNodeUpdated();
void emitTreeChanged();
virtual Node *trim(const QSet<Node *> &keepers);
virtual FileNode *asFileNode() { return nullptr; }
virtual const FileNode *asFileNode() const { return nullptr; }
virtual FolderNode *asFolderNode() { return nullptr; }
@@ -208,8 +206,6 @@ public:
QString displayName() const override;
QIcon icon() const;
Node *trim(const QSet<Node *> &keepers) override;
QList<FileNode *> fileNodes() const;
FileNode *fileNode(const Utils::FileName &file) const;
FileNode *recursiveFileNode(const Utils::FileName &file) const;
@@ -304,14 +300,13 @@ public:
ProjectNode *projectNode(const Utils::FileName &file) const;
// all subFolders that are projects
QList<ProjectNode*> projectNodes() const;
void addProjectNodes(const QList<ProjectNode*> &subProjects);
void removeProjectNodes(const QList<ProjectNode*> &subProjects);
void addProjectNode(ProjectNode *subProject);
void removeProjectNodes();
void removeProjectNode(ProjectNode *subProject);
ProjectNode *asProjectNode() final { return this; }
const ProjectNode *asProjectNode() const final { return this; }
Node *trim(const QSet<Node *> &keepers) override;
protected:
// this is just the in-memory representation, a subclass
// will add the persistent stuff

View File

@@ -681,7 +681,6 @@ void QbsProductNode::setQbsProductData(const qbs::Project &project, const qbs::P
idx->setAbsoluteFilePathAndLine(Utils::FileName::fromString(prd.location().filePath()),
prd.location().line());
QList<ProjectExplorer::ProjectNode *> toAdd;
QList<ProjectExplorer::ProjectNode *> toRemove = projectNodes();
foreach (const qbs::GroupData &grp, prd.groups()) {
@@ -697,7 +696,7 @@ void QbsProductNode::setQbsProductData(const qbs::Project &project, const qbs::P
gn->updateQbsGroupData(grp, productPath, productWasEnabled, productIsEnabled);
} else {
gn = new QbsGroupNode(grp, productPath);
toAdd.append(gn);
addProjectNode(gn);
}
}
@@ -708,8 +707,8 @@ void QbsProductNode::setQbsProductData(const qbs::Project &project, const qbs::P
prd.buildDirectory(), true, true);
}
addProjectNodes(toAdd);
removeProjectNodes(toRemove);
for (ProjectNode *node : toRemove)
removeProjectNode(node);
m_qbsProductData = prd;
if (updateExisting)
@@ -761,7 +760,6 @@ QbsProjectNode::~QbsProjectNode()
void QbsProjectNode::update(const qbs::Project &qbsProject, const qbs::ProjectData &prjData)
{
QList<ProjectExplorer::ProjectNode *> toAdd;
QList<ProjectExplorer::ProjectNode *> toRemove = projectNodes();
foreach (const qbs::ProjectData &subData, prjData.subProjects()) {
@@ -770,7 +768,7 @@ void QbsProjectNode::update(const qbs::Project &qbsProject, const qbs::ProjectDa
auto subProject =
new QbsProjectNode(Utils::FileName::fromString(subData.location().filePath()));
subProject->update(qbsProject, subData);
toAdd << subProject;
addProjectNode(subProject);
} else {
qn->update(qbsProject, subData);
toRemove.removeOne(qn);
@@ -780,7 +778,7 @@ void QbsProjectNode::update(const qbs::Project &qbsProject, const qbs::ProjectDa
foreach (const qbs::ProductData &prd, prjData.products()) {
QbsProductNode *qn = findProductNode(QbsProject::uniqueProductName(prd));
if (!qn) {
toAdd << new QbsProductNode(qbsProject, prd);
addProjectNode(new QbsProductNode(qbsProject, prd));
} else {
qn->setQbsProductData(qbsProject, prd);
toRemove.removeOne(qn);
@@ -792,8 +790,8 @@ void QbsProjectNode::update(const qbs::Project &qbsProject, const qbs::ProjectDa
else
setDisplayName(project()->displayName());
removeProjectNodes(toRemove);
addProjectNodes(toAdd);
foreach (ProjectNode *node, toRemove)
removeProjectNode(node);
m_projectData = prjData;
}

View File

@@ -2043,7 +2043,7 @@ void QmakeProFileNode::applyEvaluate(EvalResult *evalResult)
// delete files && folders && projects
setFileNodes({});
removeProjectNodes(projectNodes());
removeProjectNodes();
setFolderNodes({});
m_projectType = InvalidProject;
@@ -2065,7 +2065,7 @@ void QmakeProFileNode::applyEvaluate(EvalResult *evalResult)
}
setFileNodes({});
removeProjectNodes(projectNodes());
removeProjectNodes();
setFolderNodes({});
m_projectType = result->projectType;
@@ -2091,7 +2091,6 @@ void QmakeProFileNode::applyEvaluate(EvalResult *evalResult)
Utils::sort(existingProjectNodes, sortByPath);
// result is already sorted
QList<ProjectNode*> toAdd;
QList<ProjectNode*> toRemove;
QList<ProjectNode*>::const_iterator existingIt = existingProjectNodes.constBegin();
@@ -2130,21 +2129,19 @@ void QmakeProFileNode::applyEvaluate(EvalResult *evalResult)
} else {
if (nodeToAdd->proFile) {
QmakePriFileNode *qmakePriFileNode = new QmakePriFileNode(m_project, this, nodeToAdd->name);
qmakePriFileNode->setParentFolderNode(pn); // Needed for loop detection
pn->addProjectNode(qmakePriFileNode);
qmakePriFileNode->setIncludedInExactParse(
(result->state == EvalResult::EvalOk) && pn->includedInExactParse());
toAdd << qmakePriFileNode;
qmakePriFileNode->update(nodeToAdd->result);
toCompare.append(qMakePair(qmakePriFileNode, nodeToAdd));
} else {
QmakeProFileNode *qmakeProFileNode = new QmakeProFileNode(m_project, nodeToAdd->name);
qmakeProFileNode->setParentFolderNode(pn); // Needed for loop detection
pn->addProjectNode(qmakeProFileNode);
qmakeProFileNode->setIncludedInExactParse(
result->exactSubdirs.contains(qmakeProFileNode->filePath())
&& pn->includedInExactParse());
qmakeProFileNode->setParseInProgress(true);
qmakeProFileNode->asyncUpdate();
toAdd << qmakeProFileNode;
}
}
} else {
@@ -2176,12 +2173,8 @@ void QmakeProFileNode::applyEvaluate(EvalResult *evalResult)
qmakeProFileNode->setValidParseRecursive(false);
qmakeProFileNode->setParseInProgressRecursive(false);
}
pn->removeProjectNode(node);
}
if (!toRemove.isEmpty())
pn->removeProjectNodes(toRemove);
if (!toAdd.isEmpty())
pn->addProjectNodes(toAdd);
}
QmakePriFileNode::update(result->includedFiles.result);

View File

@@ -91,18 +91,6 @@ static bool addFilesToResource(const Utils::FileName &resourceFile,
return true;
}
static bool sortByPrefixAndLang(ProjectExplorer::FolderNode *a, ProjectExplorer::FolderNode *b)
{
ResourceFolderNode *aa = static_cast<ResourceFolderNode *>(a);
ResourceFolderNode *bb = static_cast<ResourceFolderNode *>(b);
if (aa->prefix() < bb->prefix())
return true;
if (bb->prefix() < aa->prefix())
return false;
return aa->lang() < bb->lang();
}
ResourceTopLevelNode::ResourceTopLevelNode(
const Utils::FileName &filePath, const QString &contents,
ProjectExplorer::FolderNode *parent)