AutoTest: Ensure that removing and adding qml files is noticed

Task-number: QTCREATORBUG-17805
Change-Id: I068f6925fc39813a504205c4ef8e8b9f9e911189
Reviewed-by: David Schulz <david.schulz@qt.io>
This commit is contained in:
Christian Stenger
2017-03-06 15:24:16 +01:00
parent a095148993
commit b273d7be6a
5 changed files with 60 additions and 14 deletions

View File

@@ -114,8 +114,9 @@ void AutotestPlugin::initializeMenuEntries()
action = new QAction(tr("Re&scan Tests"), this); action = new QAction(tr("Re&scan Tests"), this);
command = ActionManager::registerAction(action, Constants::ACTION_SCAN_ID); command = ActionManager::registerAction(action, Constants::ACTION_SCAN_ID);
command->setDefaultKeySequence(QKeySequence(tr("Alt+Shift+T,Alt+S"))); command->setDefaultKeySequence(QKeySequence(tr("Alt+Shift+T,Alt+S")));
connect(action, &QAction::triggered, connect(action, &QAction::triggered, [this] () {
TestTreeModel::instance()->parser(), &TestCodeParser::updateTestTree); TestTreeModel::instance()->parser()->updateTestTree();
});
menu->addAction(command); menu->addAction(command);
ActionContainer *toolsMenu = ActionManager::actionContainer(Core::Constants::M_TOOLS); ActionContainer *toolsMenu = ActionManager::actionContainer(Core::Constants::M_TOOLS);

View File

@@ -28,16 +28,22 @@
#include "quicktestvisitors.h" #include "quicktestvisitors.h"
#include "quicktest_utils.h" #include "quicktest_utils.h"
#include "../autotest_utils.h" #include "../autotest_utils.h"
#include "../testcodeparser.h"
#include <projectexplorer/session.h>
#include <qmljs/parser/qmljsast_p.h> #include <qmljs/parser/qmljsast_p.h>
#include <qmljs/qmljsdialect.h> #include <qmljs/qmljsdialect.h>
#include <qmljstools/qmljsmodelmanager.h> #include <qmljstools/qmljsmodelmanager.h>
#include <utils/hostosinfo.h> #include <utils/hostosinfo.h>
#include <utils/qtcassert.h> #include <utils/qtcassert.h>
#include <QFileSystemWatcher>
namespace Autotest { namespace Autotest {
namespace Internal { namespace Internal {
static QFileSystemWatcher s_directoryWatcher;
TestTreeItem *QuickTestParseResult::createTestTreeItem() const TestTreeItem *QuickTestParseResult::createTestTreeItem() const
{ {
if (itemType == TestTreeItem::Root || itemType == TestTreeItem::TestDataTag) if (itemType == TestTreeItem::Root || itemType == TestTreeItem::TestDataTag)
@@ -140,6 +146,8 @@ static QList<QmlJS::Document::Ptr> scanDirectoryForQuickTestQmlFiles(const QStri
QFileInfo fi(it.fileInfo().canonicalFilePath()); QFileInfo fi(it.fileInfo().canonicalFilePath());
dirs << fi.filePath(); dirs << fi.filePath();
} }
s_directoryWatcher.addPaths(dirs);
QList<QmlJS::Document::Ptr> foundDocs; QList<QmlJS::Document::Ptr> foundDocs;
for (const QString &path : dirs) { for (const QString &path : dirs) {
@@ -227,6 +235,27 @@ static bool handleQtQuickTest(QFutureInterface<TestParseResultPtr> futureInterfa
return result; return result;
} }
QuickTestParser::QuickTestParser()
: CppParser()
{
QObject::connect(ProjectExplorer::SessionManager::instance(),
&ProjectExplorer::SessionManager::startupProjectChanged, [] {
const QStringList &dirs = s_directoryWatcher.directories();
if (!dirs.isEmpty())
s_directoryWatcher.removePaths(dirs);
});
QObject::connect(&s_directoryWatcher, &QFileSystemWatcher::directoryChanged,
[this] { TestTreeModel::instance()->parser()->emitUpdateTestTree(this); });
}
QuickTestParser::~QuickTestParser()
{
QObject::disconnect(&s_directoryWatcher, 0, 0, 0);
const QStringList &dirs = s_directoryWatcher.directories();
if (!dirs.isEmpty())
s_directoryWatcher.removePaths(dirs);
}
void QuickTestParser::init(const QStringList &filesToParse) void QuickTestParser::init(const QStringList &filesToParse)
{ {
m_qmlSnapshot = QmlJSTools::Internal::ModelManager::instance()->snapshot(); m_qmlSnapshot = QmlJSTools::Internal::ModelManager::instance()->snapshot();

View File

@@ -42,6 +42,8 @@ public:
class QuickTestParser : public CppParser class QuickTestParser : public CppParser
{ {
public: public:
QuickTestParser();
virtual ~QuickTestParser();
void init(const QStringList &filesToParse) override; void init(const QStringList &filesToParse) override;
void release() override; void release() override;
bool processDocument(QFutureInterface<TestParseResultPtr> futureInterface, bool processDocument(QFutureInterface<TestParseResultPtr> futureInterface,

View File

@@ -131,7 +131,7 @@ void TestCodeParser::syncTestFrameworks(const QVector<Core::Id> &frameworkIds)
updateTestTree(); updateTestTree();
} }
void TestCodeParser::emitUpdateTestTree() void TestCodeParser::emitUpdateTestTree(ITestParser *parser)
{ {
if (m_testCodeParsers.isEmpty()) if (m_testCodeParsers.isEmpty())
return; return;
@@ -142,10 +142,10 @@ void TestCodeParser::emitUpdateTestTree()
qCDebug(LOG) << "adding singleShot"; qCDebug(LOG) << "adding singleShot";
m_singleShotScheduled = true; m_singleShotScheduled = true;
QTimer::singleShot(1000, this, &TestCodeParser::updateTestTree); QTimer::singleShot(1000, this, [this, parser](){ updateTestTree(parser); });
} }
void TestCodeParser::updateTestTree() void TestCodeParser::updateTestTree(ITestParser *parser)
{ {
m_singleShotScheduled = false; m_singleShotScheduled = false;
if (m_codeModelParsing) { if (m_codeModelParsing) {
@@ -160,7 +160,7 @@ void TestCodeParser::updateTestTree()
m_fullUpdatePostponed = false; m_fullUpdatePostponed = false;
qCDebug(LOG) << "calling scanForTests (updateTestTree)"; qCDebug(LOG) << "calling scanForTests (updateTestTree)";
scanForTests(); scanForTests(QStringList(), parser);
} }
static QStringList filterFiles(const QString &projectDir, const QStringList &files) static QStringList filterFiles(const QString &projectDir, const QStringList &files)
@@ -315,7 +315,7 @@ static void parseFileForTests(const QVector<ITestParser *> &parsers,
} }
} }
void TestCodeParser::scanForTests(const QStringList &fileList) void TestCodeParser::scanForTests(const QStringList &fileList, ITestParser *parser)
{ {
if (m_parserState == Shutdown || m_testCodeParsers.isEmpty()) if (m_parserState == Shutdown || m_testCodeParsers.isEmpty())
return; return;
@@ -355,7 +355,14 @@ void TestCodeParser::scanForTests(const QStringList &fileList)
list = Utils::filtered(list, [] (const QString &fn) { list = Utils::filtered(list, [] (const QString &fn) {
return !fn.endsWith(".qml"); return !fn.endsWith(".qml");
}); });
m_model->markAllForRemoval(); if (parser)
TestFrameworkManager::instance()->rootNodeForTestFramework(parser->id())->markForRemovalRecursively(true);
else
m_model->markAllForRemoval();
} else if (parser) {
TestTreeItem *root = TestFrameworkManager::instance()->rootNodeForTestFramework(parser->id());
for (const QString &filePath : list)
root->markForRemovalRecursively(filePath);
} else { } else {
for (const QString &filePath : list) for (const QString &filePath : list)
m_model->markForRemoval(filePath); m_model->markForRemoval(filePath);
@@ -372,13 +379,20 @@ void TestCodeParser::scanForTests(const QStringList &fileList)
onFinished(); onFinished();
return; return;
} }
// use only a single parser or all current active?
QVector<ITestParser *> codeParsers;
if (parser)
codeParsers.append(parser);
else
codeParsers.append(m_testCodeParsers);
qCDebug(LOG) << QDateTime::currentDateTime().toString("hh:mm:ss.zzz") << "StartParsing"; qCDebug(LOG) << QDateTime::currentDateTime().toString("hh:mm:ss.zzz") << "StartParsing";
for (ITestParser *parser : m_testCodeParsers) for (ITestParser *parser : codeParsers)
parser->init(list); parser->init(list);
QFuture<TestParseResultPtr> future = Utils::map(list, QFuture<TestParseResultPtr> future = Utils::map(list,
[this](QFutureInterface<TestParseResultPtr> &fi, const QString &file) { [this, codeParsers](QFutureInterface<TestParseResultPtr> &fi, const QString &file) {
parseFileForTests(m_testCodeParsers, fi, file); parseFileForTests(codeParsers, fi, file);
}, },
Utils::MapReduceOption::Unordered, Utils::MapReduceOption::Unordered,
QThread::LowestPriority); QThread::LowestPriority);

View File

@@ -72,8 +72,8 @@ signals:
void parsingFailed(); void parsingFailed();
public: public:
void emitUpdateTestTree(); void emitUpdateTestTree(ITestParser *parser = nullptr);
void updateTestTree(); void updateTestTree(ITestParser *parser = nullptr);
void onCppDocumentUpdated(const CPlusPlus::Document::Ptr &document); void onCppDocumentUpdated(const CPlusPlus::Document::Ptr &document);
void onQmlDocumentUpdated(const QmlJS::Document::Ptr &document); void onQmlDocumentUpdated(const QmlJS::Document::Ptr &document);
void onStartupProjectChanged(ProjectExplorer::Project *project); void onStartupProjectChanged(ProjectExplorer::Project *project);
@@ -82,7 +82,7 @@ public:
private: private:
bool postponed(const QStringList &fileList); bool postponed(const QStringList &fileList);
void scanForTests(const QStringList &fileList = QStringList()); void scanForTests(const QStringList &fileList = QStringList(), ITestParser *parser = nullptr);
void onDocumentUpdated(const QString &fileName); void onDocumentUpdated(const QString &fileName);
void onTaskStarted(Core::Id type); void onTaskStarted(Core::Id type);