AutoTest: Avoid full rescans if not necessary

The file system watcher triggers way too often as it
acts not only for removal or addition of files, but
for any change like mtime or similar.
Doing always a full rescan is painful, so limit this
as much as possible to the files that have changed.

Task-number: QTCREATORBUG-18315
Change-Id: Iba4705ff58c34e998d8cf1b40761758c6fd65680
Reviewed-by: David Schulz <david.schulz@qt.io>
Reviewed-by: Christian Stenger <christian.stenger@qt.io>
This commit is contained in:
Christian Stenger
2017-06-01 11:57:57 +02:00
parent 325eaf4a62
commit 3cd688ca44
2 changed files with 50 additions and 2 deletions

View File

@@ -35,6 +35,7 @@
#include <qmljs/qmljsdialect.h>
#include <qmljstools/qmljsmodelmanager.h>
#include <utils/hostosinfo.h>
#include <utils/algorithm.h>
#include <utils/qtcassert.h>
namespace Autotest {
@@ -237,6 +238,49 @@ bool QuickTestParser::handleQtQuickTest(QFutureInterface<TestParseResultPtr> fut
return result;
}
static QMap<QString, QDateTime> qmlFilesWithMTime(const QString &directory)
{
const QFileInfoList &qmlFiles = QDir(directory).entryInfoList({ "*.qml" },
QDir::Files, QDir::Name);
QMap<QString, QDateTime> filesAndDates;
for (const QFileInfo &info : qmlFiles)
filesAndDates.insert(info.fileName(), info.lastModified());
return filesAndDates;
}
void QuickTestParser::handleDirectoryChanged(const QString &directory)
{
const QMap<QString, QDateTime> &filesAndDates = qmlFilesWithMTime(directory);
const QMap<QString, QDateTime> &watched = m_watchedFiles.value(directory);
const QStringList &keys = watched.keys();
if (filesAndDates.keys() != keys) { // removed or added files
m_watchedFiles[directory] = filesAndDates;
TestTreeModel::instance()->parser()->emitUpdateTestTree(this);
} else { // we might still have different timestamps
const bool timestampChanged = Utils::anyOf(keys, [&](const QString &file) {
return filesAndDates.value(file) != watched.value(file);
});
if (timestampChanged) {
QmlJS::PathsAndLanguages paths;
paths.maybeInsert(Utils::FileName::fromString(directory), QmlJS::Dialect::Qml);
QFutureInterface<void> future;
QmlJS::ModelManagerInterface *qmlJsMM = QmlJS::ModelManagerInterface::instance();
QmlJS::ModelManagerInterface::importScan(future, qmlJsMM->workingCopy(), paths, qmlJsMM,
true /*emitDocumentChanges*/,
false /*onlyTheLib*/,
true /*forceRescan*/ );
}
}
}
void QuickTestParser::doUpdateWatchPaths(const QStringList &directories)
{
for (const QString &dir : directories) {
m_directoryWatcher.addPath(dir);
m_watchedFiles[dir] = qmlFilesWithMTime(dir);
}
}
QuickTestParser::QuickTestParser()
: CppParser()
{
@@ -245,11 +289,12 @@ QuickTestParser::QuickTestParser()
const QStringList &dirs = m_directoryWatcher.directories();
if (!dirs.isEmpty())
m_directoryWatcher.removePaths(dirs);
m_watchedFiles.clear();
});
connect(&m_directoryWatcher, &QFileSystemWatcher::directoryChanged,
[this] { TestTreeModel::instance()->parser()->emitUpdateTestTree(this); });
this, &QuickTestParser::handleDirectoryChanged);
connect(this, &QuickTestParser::updateWatchPaths,
&m_directoryWatcher, &QFileSystemWatcher::addPaths, Qt::QueuedConnection);
this, &QuickTestParser::doUpdateWatchPaths, Qt::QueuedConnection);
}
QuickTestParser::~QuickTestParser()