forked from qt-creator/qt-creator
ProjectExplorer: allow to avoid scanning workspace subdirectories
In order to provide file watchers for the workspace project we need a way to completely exclude subdirectory of a workspace project. Otherwise we might end up with an unnecessary amount of notifications for quickly changing subdirectories like a build dir inside the workspace project. Use the previously available "files.exclude" and fully remove the entries of the project tree and avoid the scanning of the folders in that list. Change-Id: If11f62b1eabb4a7f03e4445e5f37068466feda4d Reviewed-by: Marcus Tillmanns <marcus.tillmanns@qt.io>
This commit is contained in:
@@ -54,7 +54,7 @@ bool TreeScanner::asyncScanForFiles(const Utils::FilePath &directory)
|
||||
return true;
|
||||
}
|
||||
|
||||
void TreeScanner::setFilter(TreeScanner::FileFilter filter)
|
||||
void TreeScanner::setFilter(TreeScanner::Filter filter)
|
||||
{
|
||||
if (isFinished())
|
||||
m_filter = filter;
|
||||
@@ -182,10 +182,17 @@ static DirectoryScanResult scanForFilesImpl(
|
||||
return result;
|
||||
}
|
||||
|
||||
static const Utils::MimeType &directoryMimeType()
|
||||
{
|
||||
static const Utils::MimeType mimeType = Utils::mimeTypeForName("inode/directory");
|
||||
return mimeType;
|
||||
}
|
||||
|
||||
static QList<FileNode *> scanForFilesHelper(
|
||||
TreeScanner::Promise &promise,
|
||||
const Utils::FilePath &directory,
|
||||
QDir::Filters filter,
|
||||
QDir::Filters dirfilter,
|
||||
const TreeScanner::Filter &filter,
|
||||
const std::function<FileNode *(const Utils::FilePath &)> &factory)
|
||||
{
|
||||
const QFuture<void> future(promise.future());
|
||||
@@ -195,7 +202,7 @@ static QList<FileNode *> scanForFilesHelper(
|
||||
promise.setProgressRange(0, progressRange);
|
||||
|
||||
QSet<Utils::FilePath> visited;
|
||||
const DirectoryScanResult result = scanForFilesImpl(future, directory, filter, factory, versionControls);
|
||||
const DirectoryScanResult result = scanForFilesImpl(future, directory, dirfilter, factory, versionControls);
|
||||
QList<FileNode *> fileNodes = result.nodes;
|
||||
const int progressIncrement = int(
|
||||
progressRange / static_cast<double>(fileNodes.count() + result.subDirectories.count()));
|
||||
@@ -203,11 +210,13 @@ static QList<FileNode *> scanForFilesHelper(
|
||||
QList<QPair<Utils::FilePath, int>> subDirectories;
|
||||
auto addSubDirectories = [&](const Utils::FilePaths &subdirs, int progressIncrement) {
|
||||
for (const Utils::FilePath &subdir : subdirs) {
|
||||
if (Utils::insert(visited, subdir.canonicalPath()))
|
||||
if (Utils::insert(visited, subdir.canonicalPath())
|
||||
&& !(filter && filter(directoryMimeType(), subdir))) {
|
||||
subDirectories.append(qMakePair(subdir, progressIncrement));
|
||||
else
|
||||
} else {
|
||||
promise.setProgressValue(future.progressValue() + progressIncrement);
|
||||
}
|
||||
}
|
||||
};
|
||||
addSubDirectories(result.subDirectories, progressIncrement);
|
||||
|
||||
@@ -218,7 +227,7 @@ static QList<FileNode *> scanForFilesHelper(
|
||||
|
||||
auto onSetup = [&, iterator](Utils::Async<DirectoryScanResult> &task) {
|
||||
task.setConcurrentCallData(
|
||||
scanForFilesImpl, future, iterator->first, filter, factory, versionControls);
|
||||
scanForFilesImpl, future, iterator->first, dirfilter, factory, versionControls);
|
||||
};
|
||||
|
||||
auto onDone = [&, iterator](const Utils::Async<DirectoryScanResult> &task) {
|
||||
@@ -250,12 +259,12 @@ static QList<FileNode *> scanForFilesHelper(
|
||||
void TreeScanner::scanForFiles(
|
||||
Promise &promise,
|
||||
const Utils::FilePath &directory,
|
||||
const FileFilter &filter,
|
||||
const Filter &filter,
|
||||
QDir::Filters dirFilter,
|
||||
const FileTypeFactory &factory)
|
||||
{
|
||||
QList<FileNode *> nodes = scanForFilesHelper(
|
||||
promise, directory, dirFilter, [&filter, &factory](const Utils::FilePath &fn) -> FileNode * {
|
||||
promise, directory, dirFilter, filter, [&filter, &factory](const Utils::FilePath &fn) -> FileNode * {
|
||||
const Utils::MimeType mimeType = Utils::mimeTypesForFileName(fn.path()).value(0);
|
||||
|
||||
// Skip some files during scan.
|
||||
|
@@ -33,7 +33,7 @@ public:
|
||||
using FutureWatcher = QFutureWatcher<Result>;
|
||||
using Promise = QPromise<Result>;
|
||||
|
||||
using FileFilter = std::function<bool(const Utils::MimeType &, const Utils::FilePath &)>;
|
||||
using Filter = std::function<bool(const Utils::MimeType &, const Utils::FilePath &)>;
|
||||
using FileTypeFactory = std::function<ProjectExplorer::FileType(const Utils::MimeType &, const Utils::FilePath &)>;
|
||||
|
||||
explicit TreeScanner(QObject *parent = nullptr);
|
||||
@@ -43,7 +43,7 @@ public:
|
||||
bool asyncScanForFiles(const Utils::FilePath& directory);
|
||||
|
||||
// Setup filter for ignored files
|
||||
void setFilter(FileFilter filter);
|
||||
void setFilter(Filter filter);
|
||||
|
||||
// Setup dir filters for scanned folders
|
||||
void setDirFilter(QDir::Filters dirFilter);
|
||||
@@ -74,12 +74,12 @@ signals:
|
||||
private:
|
||||
static void scanForFiles(Promise &fi,
|
||||
const Utils::FilePath &directory,
|
||||
const FileFilter &filter,
|
||||
const Filter &filter,
|
||||
QDir::Filters dirFilter,
|
||||
const FileTypeFactory &factory);
|
||||
|
||||
private:
|
||||
FileFilter m_filter;
|
||||
Filter m_filter;
|
||||
QDir::Filters m_dirFilter = QDir::AllEntries | QDir::NoDotAndDotDot;
|
||||
FileTypeFactory m_factory;
|
||||
|
||||
|
@@ -49,18 +49,6 @@ const expected_str<QJsonObject> projectDefinition(const Project *project)
|
||||
return {};
|
||||
}
|
||||
|
||||
static bool checkEnabled(FolderNode *fn)
|
||||
{
|
||||
if (fn->findChildFileNode([](FileNode *fn) { return fn->isEnabled(); }))
|
||||
return true;
|
||||
|
||||
if (fn->findChildFolderNode([](FolderNode *fn) { return checkEnabled(fn); }))
|
||||
return true;
|
||||
|
||||
fn->setEnabled(false);
|
||||
return false;
|
||||
}
|
||||
|
||||
class WorkspaceBuildSystem final : public BuildSystem
|
||||
{
|
||||
public:
|
||||
@@ -71,15 +59,10 @@ public:
|
||||
auto root = std::make_unique<ProjectNode>(projectDirectory());
|
||||
root->setDisplayName(target()->project()->displayName());
|
||||
std::vector<std::unique_ptr<FileNode>> nodePtrs
|
||||
= Utils::transform<std::vector>(m_scanner.release().allFiles, [this](FileNode *fn) {
|
||||
fn->setEnabled(!Utils::anyOf(
|
||||
m_filters, [path = fn->path().path()](const QRegularExpression &filter) {
|
||||
return filter.match(path).hasMatch();
|
||||
}));
|
||||
= Utils::transform<std::vector>(m_scanner.release().allFiles, [](FileNode *fn) {
|
||||
return std::unique_ptr<FileNode>(fn);
|
||||
});
|
||||
root->addNestedNodes(std::move(nodePtrs));
|
||||
root->forEachFolderNode(&checkEnabled);
|
||||
setRootProjectNode(std::move(root));
|
||||
|
||||
m_parseGuard.markAsSuccess();
|
||||
@@ -88,6 +71,11 @@ public:
|
||||
emitBuildSystemUpdated();
|
||||
});
|
||||
m_scanner.setDirFilter(QDir::AllEntries | QDir::NoDotAndDotDot | QDir::Hidden);
|
||||
m_scanner.setFilter([&](const Utils::MimeType &, const Utils::FilePath &filePath) {
|
||||
return Utils::anyOf(m_filters, [filePath](const QRegularExpression &filter) {
|
||||
return filter.match(filePath.path()).hasMatch();
|
||||
});
|
||||
});
|
||||
|
||||
connect(target()->project(),
|
||||
&Project::projectFileIsDirty,
|
||||
@@ -110,8 +98,6 @@ public:
|
||||
for (const QJsonValue &excludeJson : excludesJson) {
|
||||
if (excludeJson.isString()) {
|
||||
FilePath absolute = projectPath.pathAppended(excludeJson.toString());
|
||||
if (absolute.isDir())
|
||||
absolute = absolute.pathAppended("*");
|
||||
m_filters << QRegularExpression(
|
||||
Utils::wildcardToRegularExpression(absolute.path()),
|
||||
QRegularExpression::CaseInsensitiveOption);
|
||||
|
Reference in New Issue
Block a user