AutoTest: Reduce re-parsings while editing single file

Change-Id: If3dbcb3026733873881921cb9208b7c9da33c8de
Reviewed-by: David Schulz <david.schulz@qt.io>
This commit is contained in:
Christian Stenger
2016-10-24 12:51:03 +02:00
parent 99a82f7035
commit 2b27f30538
2 changed files with 49 additions and 16 deletions

View File

@@ -45,7 +45,6 @@
#include <QFuture> #include <QFuture>
#include <QFutureInterface> #include <QFutureInterface>
#include <QLoggingCategory> #include <QLoggingCategory>
#include <QTimer>
static Q_LOGGING_CATEGORY(LOG, "qtc.autotest.testcodeparser") static Q_LOGGING_CATEGORY(LOG, "qtc.autotest.testcodeparser")
@@ -54,13 +53,7 @@ namespace Internal {
TestCodeParser::TestCodeParser(TestTreeModel *parent) TestCodeParser::TestCodeParser(TestTreeModel *parent)
: QObject(parent), : QObject(parent),
m_model(parent), m_model(parent)
m_codeModelParsing(false),
m_fullUpdatePostponed(false),
m_partialUpdatePostponed(false),
m_dirty(false),
m_singleShotScheduled(false),
m_parserState(Disabled)
{ {
// connect to ProgressManager to postpone test parsing when CppModelManager is parsing // connect to ProgressManager to postpone test parsing when CppModelManager is parsing
auto progressManager = qobject_cast<Core::ProgressManager *>(Core::ProgressManager::instance()); auto progressManager = qobject_cast<Core::ProgressManager *>(Core::ProgressManager::instance());
@@ -77,6 +70,8 @@ TestCodeParser::TestCodeParser(TestTreeModel *parent)
emit testParseResultReady(m_futureWatcher.resultAt(index)); emit testParseResultReady(m_futureWatcher.resultAt(index));
}); });
connect(this, &TestCodeParser::parsingFinished, this, &TestCodeParser::releaseParserInternals); connect(this, &TestCodeParser::parsingFinished, this, &TestCodeParser::releaseParserInternals);
m_reparseTimer.setSingleShot(true);
connect(&m_reparseTimer, &QTimer::timeout, this, &TestCodeParser::parsePostponedFiles);
} }
TestCodeParser::~TestCodeParser() TestCodeParser::~TestCodeParser()
@@ -111,6 +106,7 @@ void TestCodeParser::setState(State state)
} else if (m_partialUpdatePostponed) { } else if (m_partialUpdatePostponed) {
m_partialUpdatePostponed = false; m_partialUpdatePostponed = false;
qCDebug(LOG) << "calling scanForTests with postponed files (setState)"; qCDebug(LOG) << "calling scanForTests with postponed files (setState)";
if (!m_reparseTimer.isActive())
scanForTests(m_postponedFiles.toList()); scanForTests(m_postponedFiles.toList());
} }
} }
@@ -267,6 +263,30 @@ bool TestCodeParser::postponed(const QStringList &fileList)
{ {
switch (m_parserState) { switch (m_parserState) {
case Idle: case Idle:
if (fileList.size() == 1) {
if (m_reparseTimerTimedOut)
return false;
switch (m_postponedFiles.size()) {
case 0:
m_postponedFiles.insert(fileList.first());
m_reparseTimer.setInterval(1000);
m_reparseTimer.start();
return true;
case 1:
if (m_postponedFiles.contains(fileList.first())) {
m_reparseTimer.start();
return true;
}
// intentional fall-through
default:
m_postponedFiles.insert(fileList.first());
m_reparseTimer.stop();
m_reparseTimer.setInterval(0);
m_reparseTimerTimedOut = false;
m_reparseTimer.start();
return true;
}
}
return false; return false;
case PartialParse: case PartialParse:
case FullParse: case FullParse:
@@ -313,6 +333,8 @@ void TestCodeParser::scanForTests(const QStringList &fileList)
if (postponed(fileList)) if (postponed(fileList))
return; return;
m_reparseTimer.stop();
m_reparseTimerTimedOut = false;
m_postponedFiles.clear(); m_postponedFiles.clear();
bool isFullParse = fileList.isEmpty(); bool isFullParse = fileList.isEmpty();
QStringList list; QStringList list;
@@ -436,6 +458,7 @@ void TestCodeParser::onPartialParsingFinished()
} else if (m_partialUpdatePostponed) { } else if (m_partialUpdatePostponed) {
m_partialUpdatePostponed = false; m_partialUpdatePostponed = false;
qCDebug(LOG) << "calling scanForTests with postponed files (onPartialParsingFinished)"; qCDebug(LOG) << "calling scanForTests with postponed files (onPartialParsingFinished)";
if (!m_reparseTimer.isActive())
scanForTests(m_postponedFiles.toList()); scanForTests(m_postponedFiles.toList());
} else { } else {
m_dirty |= m_codeModelParsing; m_dirty |= m_codeModelParsing;
@@ -454,6 +477,12 @@ void TestCodeParser::onPartialParsingFinished()
} }
} }
void TestCodeParser::parsePostponedFiles()
{
m_reparseTimerTimedOut = true;
scanForTests(m_postponedFiles.toList());
}
void TestCodeParser::releaseParserInternals() void TestCodeParser::releaseParserInternals()
{ {
for (ITestParser *parser : m_testCodeParsers) for (ITestParser *parser : m_testCodeParsers)

View File

@@ -32,6 +32,7 @@
#include <QObject> #include <QObject>
#include <QMap> #include <QMap>
#include <QFutureWatcher> #include <QFutureWatcher>
#include <QTimer>
namespace Core { namespace Core {
class Id; class Id;
@@ -89,19 +90,22 @@ private:
void onAllTasksFinished(Core::Id type); void onAllTasksFinished(Core::Id type);
void onFinished(); void onFinished();
void onPartialParsingFinished(); void onPartialParsingFinished();
void parsePostponedFiles();
void releaseParserInternals(); void releaseParserInternals();
TestTreeModel *m_model; TestTreeModel *m_model;
bool m_codeModelParsing; bool m_codeModelParsing = false;
bool m_fullUpdatePostponed; bool m_fullUpdatePostponed = false;
bool m_partialUpdatePostponed; bool m_partialUpdatePostponed = false;
bool m_dirty; bool m_dirty = false;
bool m_singleShotScheduled; bool m_singleShotScheduled = false;
bool m_reparseTimerTimedOut = false;
QSet<QString> m_postponedFiles; QSet<QString> m_postponedFiles;
State m_parserState; State m_parserState = Disabled;
QFutureWatcher<TestParseResultPtr> m_futureWatcher; QFutureWatcher<TestParseResultPtr> m_futureWatcher;
QVector<ITestParser *> m_testCodeParsers; // ptrs are still owned by TestFrameworkManager QVector<ITestParser *> m_testCodeParsers; // ptrs are still owned by TestFrameworkManager
QTimer m_reparseTimer;
}; };
} // namespace Internal } // namespace Internal