forked from qt-creator/qt-creator
AutoTest: Allow re-parsing with a sub-set of parsers
Avoid expanding parsing over all parsers if we trigger a re-parse for a different parser and there is already a re-parse postponed. Change-Id: If74480fea2c671b32083fb7cf3f4dc4c418e6e33 Reviewed-by: Christian Stenger <christian.stenger@qt.io> Reviewed-by: David Schulz <david.schulz@qt.io>
This commit is contained in:
@@ -81,10 +81,6 @@ TestCodeParser::TestCodeParser(TestTreeModel *parent)
|
|||||||
m_threadPool->setMaxThreadCount(std::max(QThread::idealThreadCount()/4, 1));
|
m_threadPool->setMaxThreadCount(std::max(QThread::idealThreadCount()/4, 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
TestCodeParser::~TestCodeParser()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void TestCodeParser::setState(State state)
|
void TestCodeParser::setState(State state)
|
||||||
{
|
{
|
||||||
if (m_parserState == Shutdown)
|
if (m_parserState == Shutdown)
|
||||||
@@ -138,28 +134,33 @@ void TestCodeParser::emitUpdateTestTree(ITestParser *parser)
|
|||||||
{
|
{
|
||||||
if (m_testCodeParsers.isEmpty())
|
if (m_testCodeParsers.isEmpty())
|
||||||
return;
|
return;
|
||||||
|
if (parser)
|
||||||
|
m_updateParsers.insert(parser->id());
|
||||||
|
else
|
||||||
|
m_updateParsers.clear();
|
||||||
if (m_singleShotScheduled) {
|
if (m_singleShotScheduled) {
|
||||||
if (m_updateParser && parser != m_updateParser)
|
|
||||||
m_updateParser = nullptr;
|
|
||||||
qCDebug(LOG) << "not scheduling another updateTestTree";
|
qCDebug(LOG) << "not scheduling another updateTestTree";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
qCDebug(LOG) << "adding singleShot";
|
qCDebug(LOG) << "adding singleShot";
|
||||||
m_singleShotScheduled = true;
|
m_singleShotScheduled = true;
|
||||||
m_updateParser = parser;
|
QTimer::singleShot(1000, this, [this]() { updateTestTree(m_updateParsers); });
|
||||||
QTimer::singleShot(1000, this, [this](){ updateTestTree(m_updateParser); });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestCodeParser::updateTestTree(ITestParser *parser)
|
void TestCodeParser::updateTestTree(const QSet<Core::Id> &frameworkIds)
|
||||||
{
|
{
|
||||||
m_singleShotScheduled = false;
|
m_singleShotScheduled = false;
|
||||||
if (m_codeModelParsing) {
|
if (m_codeModelParsing) {
|
||||||
m_fullUpdatePostponed = true;
|
m_fullUpdatePostponed = true;
|
||||||
m_partialUpdatePostponed = false;
|
m_partialUpdatePostponed = false;
|
||||||
m_postponedFiles.clear();
|
m_postponedFiles.clear();
|
||||||
if (!parser || parser != m_updateParser)
|
if (frameworkIds.isEmpty()) {
|
||||||
m_updateParser = nullptr;
|
m_updateParsers.clear();
|
||||||
|
} else {
|
||||||
|
for (const Core::Id &id : frameworkIds)
|
||||||
|
m_updateParsers.insert(id);
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -168,7 +169,12 @@ void TestCodeParser::updateTestTree(ITestParser *parser)
|
|||||||
|
|
||||||
m_fullUpdatePostponed = false;
|
m_fullUpdatePostponed = false;
|
||||||
qCDebug(LOG) << "calling scanForTests (updateTestTree)";
|
qCDebug(LOG) << "calling scanForTests (updateTestTree)";
|
||||||
scanForTests(QStringList(), parser);
|
QList<Core::Id> sortedFrameworks = Utils::toList(frameworkIds);
|
||||||
|
Utils::sort(sortedFrameworks, [manager = TestFrameworkManager::instance()]
|
||||||
|
(const Core::Id &lhs, const Core::Id &rhs) {
|
||||||
|
return manager->priority(lhs) < manager->priority(rhs);
|
||||||
|
});
|
||||||
|
scanForTests(QStringList(), sortedFrameworks);
|
||||||
}
|
}
|
||||||
|
|
||||||
// used internally to indicate a parse that failed due to having triggered a parse for a file that
|
// used internally to indicate a parse that failed due to having triggered a parse for a file that
|
||||||
@@ -291,7 +297,7 @@ bool TestCodeParser::postponed(const QStringList &fileList)
|
|||||||
QTC_ASSERT(false, return false); // should not happen at all
|
QTC_ASSERT(false, return false); // should not happen at all
|
||||||
}
|
}
|
||||||
|
|
||||||
static void parseFileForTests(const QVector<ITestParser *> &parsers,
|
static void parseFileForTests(const QList<ITestParser *> &parsers,
|
||||||
QFutureInterface<TestParseResultPtr> &futureInterface,
|
QFutureInterface<TestParseResultPtr> &futureInterface,
|
||||||
const QString &fileName)
|
const QString &fileName)
|
||||||
{
|
{
|
||||||
@@ -303,12 +309,10 @@ static void parseFileForTests(const QVector<ITestParser *> &parsers,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestCodeParser::scanForTests(const QStringList &fileList, ITestParser *parser)
|
void TestCodeParser::scanForTests(const QStringList &fileList, const QList<Core::Id> &parserIds)
|
||||||
{
|
{
|
||||||
if (m_parserState == Shutdown || m_testCodeParsers.isEmpty())
|
if (m_parserState == Shutdown || m_testCodeParsers.isEmpty())
|
||||||
return;
|
return;
|
||||||
if (parser && !m_testCodeParsers.contains(parser))
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (postponed(fileList))
|
if (postponed(fileList))
|
||||||
return;
|
return;
|
||||||
@@ -339,20 +343,24 @@ void TestCodeParser::scanForTests(const QStringList &fileList, ITestParser *pars
|
|||||||
}
|
}
|
||||||
|
|
||||||
parsingHasFailed = false;
|
parsingHasFailed = false;
|
||||||
|
TestFrameworkManager *manager = TestFrameworkManager::instance();
|
||||||
if (isFullParse) {
|
if (isFullParse) {
|
||||||
// remove qml files as they will be found automatically by the referencing cpp file
|
// remove qml files as they will be found automatically by the referencing cpp file
|
||||||
list = Utils::filtered(list, [] (const QString &fn) {
|
list = Utils::filtered(list, [] (const QString &fn) {
|
||||||
return !fn.endsWith(".qml");
|
return !fn.endsWith(".qml");
|
||||||
});
|
});
|
||||||
if (parser)
|
if (!parserIds.isEmpty()) {
|
||||||
TestFrameworkManager::instance()->rootNodeForTestFramework(parser->id())->markForRemovalRecursively(true);
|
for (const Core::Id &id : parserIds)
|
||||||
else
|
manager->rootNodeForTestFramework(id)->markForRemovalRecursively(true);
|
||||||
|
} else {
|
||||||
m_model->markAllForRemoval();
|
m_model->markAllForRemoval();
|
||||||
} else if (parser) {
|
}
|
||||||
TestTreeItem *root = TestFrameworkManager::instance()->rootNodeForTestFramework(parser->id());
|
} else if (!parserIds.isEmpty()) {
|
||||||
for (const QString &filePath : list)
|
for (const Core::Id &id : parserIds) {
|
||||||
root->markForRemovalRecursively(filePath);
|
TestTreeItem *root = manager->rootNodeForTestFramework(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);
|
||||||
@@ -370,11 +378,11 @@ void TestCodeParser::scanForTests(const QStringList &fileList, ITestParser *pars
|
|||||||
}
|
}
|
||||||
|
|
||||||
// use only a single parser or all current active?
|
// use only a single parser or all current active?
|
||||||
QVector<ITestParser *> codeParsers;
|
const QList<ITestParser *> codeParsers
|
||||||
if (parser)
|
= parserIds.isEmpty() ? m_testCodeParsers
|
||||||
codeParsers.append(parser);
|
: Utils::transform(parserIds, [](const Core::Id &id) {
|
||||||
else
|
return TestFrameworkManager::instance()->testParserForTestFramework(id);
|
||||||
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 : codeParsers)
|
for (ITestParser *parser : codeParsers)
|
||||||
parser->init(list, isFullParse);
|
parser->init(list, isFullParse);
|
||||||
@@ -442,7 +450,7 @@ void TestCodeParser::onFinished()
|
|||||||
} else {
|
} else {
|
||||||
qCDebug(LOG) << "emitting parsingFinished"
|
qCDebug(LOG) << "emitting parsingFinished"
|
||||||
<< "(onFinished, FullParse, nothing postponed, parsing succeeded)";
|
<< "(onFinished, FullParse, nothing postponed, parsing succeeded)";
|
||||||
m_updateParser = nullptr;
|
m_updateParsers.clear();
|
||||||
emit parsingFinished();
|
emit parsingFinished();
|
||||||
qCDebug(LOG) << QDateTime::currentDateTime().toString("hh:mm:ss.zzz") << "ParsingFin";
|
qCDebug(LOG) << QDateTime::currentDateTime().toString("hh:mm:ss.zzz") << "ParsingFin";
|
||||||
}
|
}
|
||||||
@@ -465,7 +473,7 @@ void TestCodeParser::onPartialParsingFinished()
|
|||||||
if (m_fullUpdatePostponed) {
|
if (m_fullUpdatePostponed) {
|
||||||
m_fullUpdatePostponed = false;
|
m_fullUpdatePostponed = false;
|
||||||
qCDebug(LOG) << "calling updateTestTree (onPartialParsingFinished)";
|
qCDebug(LOG) << "calling updateTestTree (onPartialParsingFinished)";
|
||||||
updateTestTree(m_updateParser);
|
updateTestTree(m_updateParsers);
|
||||||
} 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)";
|
||||||
@@ -479,7 +487,7 @@ void TestCodeParser::onPartialParsingFinished()
|
|||||||
} else if (!m_singleShotScheduled) {
|
} else if (!m_singleShotScheduled) {
|
||||||
qCDebug(LOG) << "emitting parsingFinished"
|
qCDebug(LOG) << "emitting parsingFinished"
|
||||||
<< "(onPartialParsingFinished, nothing postponed, not dirty)";
|
<< "(onPartialParsingFinished, nothing postponed, not dirty)";
|
||||||
m_updateParser = nullptr;
|
m_updateParsers.clear();
|
||||||
emit parsingFinished();
|
emit parsingFinished();
|
||||||
qCDebug(LOG) << QDateTime::currentDateTime().toString("hh:mm:ss.zzz") << "ParsingFin";
|
qCDebug(LOG) << QDateTime::currentDateTime().toString("hh:mm:ss.zzz") << "ParsingFin";
|
||||||
} else {
|
} else {
|
||||||
|
@@ -57,7 +57,6 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
explicit TestCodeParser(TestTreeModel *parent = nullptr);
|
explicit TestCodeParser(TestTreeModel *parent = nullptr);
|
||||||
virtual ~TestCodeParser();
|
|
||||||
void setState(State state);
|
void setState(State state);
|
||||||
State state() const { return m_parserState; }
|
State state() const { return m_parserState; }
|
||||||
bool isParsing() const { return m_parserState == PartialParse || m_parserState == FullParse; }
|
bool isParsing() const { return m_parserState == PartialParse || m_parserState == FullParse; }
|
||||||
@@ -77,7 +76,7 @@ signals:
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
void emitUpdateTestTree(ITestParser *parser = nullptr);
|
void emitUpdateTestTree(ITestParser *parser = nullptr);
|
||||||
void updateTestTree(ITestParser *parser = nullptr);
|
void updateTestTree(const QSet<Core::Id> &frameworkIds = {});
|
||||||
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);
|
||||||
@@ -86,7 +85,8 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
bool postponed(const QStringList &fileList);
|
bool postponed(const QStringList &fileList);
|
||||||
void scanForTests(const QStringList &fileList = QStringList(), ITestParser *parser = nullptr);
|
void scanForTests(const QStringList &fileList = QStringList(),
|
||||||
|
const QList<Core::Id> &parserIds = {});
|
||||||
|
|
||||||
// qml files must be handled slightly different
|
// qml files must be handled slightly different
|
||||||
void onDocumentUpdated(const QString &fileName, bool isQmlFile = false);
|
void onDocumentUpdated(const QString &fileName, bool isQmlFile = false);
|
||||||
@@ -108,9 +108,9 @@ private:
|
|||||||
QSet<QString> m_postponedFiles;
|
QSet<QString> m_postponedFiles;
|
||||||
State m_parserState = Idle;
|
State m_parserState = Idle;
|
||||||
QFutureWatcher<TestParseResultPtr> m_futureWatcher;
|
QFutureWatcher<TestParseResultPtr> m_futureWatcher;
|
||||||
QVector<ITestParser *> m_testCodeParsers; // ptrs are still owned by TestFrameworkManager
|
QList<ITestParser *> m_testCodeParsers; // ptrs are still owned by TestFrameworkManager
|
||||||
QTimer m_reparseTimer;
|
QTimer m_reparseTimer;
|
||||||
ITestParser *m_updateParser = nullptr;
|
QSet<Core::Id> m_updateParsers;
|
||||||
QThreadPool *m_threadPool = nullptr;
|
QThreadPool *m_threadPool = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user