CMake: Do not create file system node in main thread

The file system scanning was already in a thread, but creating a tree
from the flat list of file nodes was still done in the main thread.
Creating the tree looks for and creates folder nodes as needed for each
file node, which is not that big of a deal but still takes 1/3 of a
second for the Qt Creator source tree.

Task-number: QTCREATORBUG-25783
Change-Id: I28948ed3ff5233f6fc4b86e93da94d882b81e231
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Cristian Adam <cristian.adam@qt.io>
This commit is contained in:
Eike Ziller
2021-06-16 11:33:35 +02:00
parent fd6ec7da25
commit 9109a6895e
13 changed files with 191 additions and 95 deletions

View File

@@ -37,7 +37,6 @@
#include <coreplugin/iversioncontrol.h>
#include <coreplugin/vcsmanager.h>
#include <utils/algorithm.h>
#include <utils/fileutils.h>
#include <utils/hostosinfo.h>
#include <utils/mimetypes/mimedatabase.h>
@@ -384,62 +383,6 @@ FileType FileNode::fileType() const
return m_fileType;
}
static QList<FileNode *> scanForFilesRecursively(QFutureInterface<QList<FileNode*>> &future,
double progressStart, double progressRange,
const Utils::FilePath &directory,
const std::function<FileNode *(const Utils::FilePath &)> factory,
QSet<QString> &visited,
const QList<Core::IVersionControl*> &versionControls)
{
QList<FileNode *> result;
const QDir baseDir = QDir(directory.toString());
// Do not follow directory loops:
const int visitedCount = visited.count();
visited.insert(baseDir.canonicalPath());
if (visitedCount == visited.count())
return result;
const QFileInfoList entries = baseDir.entryInfoList(QStringList(), QDir::AllEntries|QDir::NoDotAndDotDot);
double progress = 0;
const double progressIncrement = progressRange / static_cast<double>(entries.count());
int lastIntProgress = 0;
for (const QFileInfo &entry : entries) {
if (future.isCanceled())
return result;
const Utils::FilePath entryName = Utils::FilePath::fromString(entry.absoluteFilePath());
if (!Utils::contains(versionControls, [&entryName](const Core::IVersionControl *vc) {
return vc->isVcsFileOrDirectory(entryName);
})) {
if (entry.isDir())
result.append(scanForFilesRecursively(future, progress, progressIncrement, entryName, factory, visited, versionControls));
else if (FileNode *node = factory(entryName))
result.append(node);
}
progress += progressIncrement;
const int intProgress = std::min(static_cast<int>(progressStart + progress), future.progressMaximum());
if (lastIntProgress < intProgress) {
future.setProgressValue(intProgress);
lastIntProgress = intProgress;
}
}
future.setProgressValue(std::min(static_cast<int>(progressStart + progressRange), future.progressMaximum()));
return result;
}
QList<FileNode *>
FileNode::scanForFiles(QFutureInterface<QList<FileNode *>> &future,
const Utils::FilePath &directory,
const std::function<FileNode *(const Utils::FilePath &)> factory)
{
QSet<QString> visited;
future.setProgressRange(0, 1000000);
return scanForFilesRecursively(future, 0.0, 1000000.0, directory, factory, visited,
Core::VcsManager::versionControls());
}
bool FileNode::supportsAction(ProjectAction action, const Node *node) const
{
if (action == InheritedFromParent)