CMake: Fix some more SOFT-ASSERTS in CMake server-mode

Fix two more SOFT-ASSERTs in CMake server-mode that could be triggered
by complex projects.

Move and simplify search functionality into FolderNode and use that instead
of hand-crafting a custom tree search in CMake.

Change-Id: If4bde5c4a7ff84c7d5dba4f595e99b39f54ac8aa
Reviewed-by: Tim Jenssen <tim.jenssen@qt.io>
This commit is contained in:
Tobias Hunger
2017-03-14 16:21:33 +01:00
parent 6e91fe5046
commit 1621aaa26e
3 changed files with 43 additions and 22 deletions

View File

@@ -540,28 +540,16 @@ void ServerModeReader::addCMakeLists(CMakeProjectNode *root, const QList<FileNod
}); });
} }
static CMakeListsNode *findCMakeNode(FolderNode *root, const Utils::FileName &dir) static ProjectNode *findCMakeNode(ProjectNode *root, const Utils::FileName &dir)
{ {
const Utils::FileName stepDir = dir; Node *n = root->findNode([&dir](Node *n) { return n->asProjectNode() && n->filePath() == dir; });
const Utils::FileName topDir = root->filePath(); return n ? n->asProjectNode() : nullptr;
QStringList relative = stepDir.relativeChildPath(topDir).toString().split('/', QString::SkipEmptyParts);
FolderNode *result = root;
while (!relative.isEmpty()) {
Utils::FileName nextFullPath = result->filePath();
nextFullPath.appendPath(relative.takeFirst());
result = findOrDefault(result->folderNodes(), Utils::equal(&FolderNode::filePath, nextFullPath));
if (!result)
return nullptr;
}
return dynamic_cast<CMakeListsNode *>(result);
} }
static CMakeProjectNode *findOrCreateProjectNode(FolderNode *root, const Utils::FileName &dir, static ProjectNode *findOrCreateProjectNode(ProjectNode *root, const Utils::FileName &dir,
const QString &displayName) const QString &displayName)
{ {
CMakeListsNode *cmln = findCMakeNode(root, dir); ProjectNode *cmln = findCMakeNode(root, dir);
QTC_ASSERT(cmln, return nullptr); QTC_ASSERT(cmln, return nullptr);
Utils::FileName projectName = dir; Utils::FileName projectName = dir;
@@ -588,17 +576,16 @@ void ServerModeReader::addProjects(CMakeProjectNode *root,
} }
for (const Project *p : projects) { for (const Project *p : projects) {
CMakeProjectNode *pNode = findOrCreateProjectNode(root, p->sourceDirectory, p->name); ProjectNode *pNode = findOrCreateProjectNode(root, p->sourceDirectory, p->name);
QTC_ASSERT(pNode, continue); QTC_ASSERT(pNode, continue);
QTC_ASSERT(root, continue);
addTargets(root, p->targets, includeFiles); addTargets(root, p->targets, includeFiles);
} }
} }
static CMakeTargetNode *findOrCreateTargetNode(FolderNode *root, const Utils::FileName &dir, static CMakeTargetNode *findOrCreateTargetNode(ProjectNode *root, const Utils::FileName &dir,
const QString &displayName) const QString &displayName)
{ {
CMakeListsNode *cmln = findCMakeNode(root, dir); ProjectNode *cmln = findCMakeNode(root, dir);
QTC_ASSERT(cmln, return nullptr); QTC_ASSERT(cmln, return nullptr);
Utils::FileName targetName = dir; Utils::FileName targetName = dir;

View File

@@ -401,6 +401,37 @@ QIcon FolderNode::icon() const
return m_icon; return m_icon;
} }
Node *FolderNode::findNode(const std::function<bool(Node *)> &filter)
{
if (filter(this))
return this;
for (Node *n : m_nodes) {
if (n->asFileNode() && filter(n)) {
return n;
} else if (FolderNode *folder = n->asFolderNode()) {
Node *result = folder->findNode(filter);
if (result)
return result;
}
}
return nullptr;
}
QList<Node *> FolderNode::findNodes(const std::function<bool(Node *)> &filter)
{
QList<Node *> result;
if (filter(this))
result.append(this);
for (Node *n : m_nodes) {
if (n->asFileNode() && filter(n))
result.append(n);
else if (FolderNode *folder = n->asFolderNode())
result.append(folder->findNode(filter));
}
return result;
}
void FolderNode::forEachNode(const std::function<void(FileNode *)> &fileTask, void FolderNode::forEachNode(const std::function<void(FileNode *)> &fileTask,
const std::function<void(FolderNode *)> &folderTask, const std::function<void(FolderNode *)> &folderTask,
const std::function<bool(const FolderNode *)> &folderFilterTask) const const std::function<bool(const FolderNode *)> &folderFilterTask) const

View File

@@ -192,6 +192,9 @@ public:
QString displayName() const override; QString displayName() const override;
QIcon icon() const; QIcon icon() const;
Node *findNode(const std::function<bool(Node *)> &filter);
QList<Node *> findNodes(const std::function<bool(Node *)> &filter);
void forEachNode(const std::function<void(FileNode *)> &fileTask, void forEachNode(const std::function<void(FileNode *)> &fileTask,
const std::function<void(FolderNode *)> &folderTask = {}, const std::function<void(FolderNode *)> &folderTask = {},
const std::function<bool(const FolderNode *)> &folderFilterTask = {}) const; const std::function<bool(const FolderNode *)> &folderFilterTask = {}) const;