forked from qt-creator/qt-creator
AutoTest: Use mark and sweep for parsing
This also removes caching from parser and the respective test info files are gone now as well. Change-Id: Ibcea68e446dea532d6addd2f16863738e497bca4 Reviewed-by: David Schulz <david.schulz@theqtcompany.com>
This commit is contained in:
@@ -11,7 +11,6 @@ SOURCES += \
|
|||||||
testtreemodel.cpp \
|
testtreemodel.cpp \
|
||||||
testtreeitem.cpp \
|
testtreeitem.cpp \
|
||||||
testvisitor.cpp \
|
testvisitor.cpp \
|
||||||
testinfo.cpp \
|
|
||||||
testcodeparser.cpp \
|
testcodeparser.cpp \
|
||||||
autotestplugin.cpp \
|
autotestplugin.cpp \
|
||||||
testrunner.cpp \
|
testrunner.cpp \
|
||||||
@@ -31,7 +30,6 @@ HEADERS += \
|
|||||||
testtreemodel.h \
|
testtreemodel.h \
|
||||||
testtreeitem.h \
|
testtreeitem.h \
|
||||||
testvisitor.h \
|
testvisitor.h \
|
||||||
testinfo.h \
|
|
||||||
testcodeparser.h \
|
testcodeparser.h \
|
||||||
autotestplugin.h \
|
autotestplugin.h \
|
||||||
autotest_global.h \
|
autotest_global.h \
|
||||||
|
|||||||
@@ -40,8 +40,6 @@ QtcPlugin {
|
|||||||
"testcodeparser.h",
|
"testcodeparser.h",
|
||||||
"testconfiguration.cpp",
|
"testconfiguration.cpp",
|
||||||
"testconfiguration.h",
|
"testconfiguration.h",
|
||||||
"testinfo.cpp",
|
|
||||||
"testinfo.h",
|
|
||||||
"testnavigationwidget.cpp",
|
"testnavigationwidget.cpp",
|
||||||
"testnavigationwidget.h",
|
"testnavigationwidget.h",
|
||||||
"testresult.cpp",
|
"testresult.cpp",
|
||||||
|
|||||||
@@ -105,11 +105,6 @@ void AutoTestUnitTests::testCodeParser()
|
|||||||
QCOMPARE(m_model->namedQuickTestsCount(), expectedNamedQuickTestsCount);
|
QCOMPARE(m_model->namedQuickTestsCount(), expectedNamedQuickTestsCount);
|
||||||
QCOMPARE(m_model->unnamedQuickTestsCount(), expectedUnnamedQuickTestsCount);
|
QCOMPARE(m_model->unnamedQuickTestsCount(), expectedUnnamedQuickTestsCount);
|
||||||
QCOMPARE(m_model->dataTagsCount(), expectedDataTagsCount);
|
QCOMPARE(m_model->dataTagsCount(), expectedDataTagsCount);
|
||||||
|
|
||||||
QCOMPARE(m_model->parser()->autoTestsCount(), expectedAutoTestsCount);
|
|
||||||
QCOMPARE(m_model->parser()->namedQuickTestsCount(), expectedNamedQuickTestsCount);
|
|
||||||
QCOMPARE(m_model->parser()->unnamedQuickTestsCount(), expectedUnnamedQuickTestsCount);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AutoTestUnitTests::testCodeParser_data()
|
void AutoTestUnitTests::testCodeParser_data()
|
||||||
@@ -162,12 +157,6 @@ void AutoTestUnitTests::testCodeParserSwitchStartup()
|
|||||||
m_isQt4 ? 0 : expectedUnnamedQuickTestsCount.at(i));
|
m_isQt4 ? 0 : expectedUnnamedQuickTestsCount.at(i));
|
||||||
QCOMPARE(m_model->dataTagsCount(),
|
QCOMPARE(m_model->dataTagsCount(),
|
||||||
expectedDataTagsCount.at(i));
|
expectedDataTagsCount.at(i));
|
||||||
|
|
||||||
QCOMPARE(m_model->parser()->autoTestsCount(), expectedAutoTestsCount.at(i));
|
|
||||||
QCOMPARE(m_model->parser()->namedQuickTestsCount(),
|
|
||||||
m_isQt4 ? 0 : expectedNamedQuickTestsCount.at(i));
|
|
||||||
QCOMPARE(m_model->parser()->unnamedQuickTestsCount(),
|
|
||||||
m_isQt4 ? 0 : expectedUnnamedQuickTestsCount.at(i));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -212,8 +201,6 @@ void AutoTestUnitTests::testCodeParserGTest()
|
|||||||
QVERIFY(parserSpy.wait(20000));
|
QVERIFY(parserSpy.wait(20000));
|
||||||
|
|
||||||
QCOMPARE(m_model->gtestNamesCount(), 6);
|
QCOMPARE(m_model->gtestNamesCount(), 6);
|
||||||
// 11 == 3 + 2 + 2 + 2 + 1 + 1, see below
|
|
||||||
QCOMPARE(m_model->parser()->gtestNamesAndSetsCount(), 11);
|
|
||||||
|
|
||||||
QMultiMap<QString, int> expectedNamesAndSets;
|
QMultiMap<QString, int> expectedNamesAndSets;
|
||||||
expectedNamesAndSets.insert(QStringLiteral("FactorialTest"), 3);
|
expectedNamesAndSets.insert(QStringLiteral("FactorialTest"), 3);
|
||||||
@@ -233,10 +220,6 @@ void AutoTestUnitTests::testCodeParserGTest()
|
|||||||
QCOMPARE(m_model->namedQuickTestsCount(), 0);
|
QCOMPARE(m_model->namedQuickTestsCount(), 0);
|
||||||
QCOMPARE(m_model->unnamedQuickTestsCount(), 0);
|
QCOMPARE(m_model->unnamedQuickTestsCount(), 0);
|
||||||
QCOMPARE(m_model->dataTagsCount(), 0);
|
QCOMPARE(m_model->dataTagsCount(), 0);
|
||||||
|
|
||||||
QCOMPARE(m_model->parser()->autoTestsCount(), 0);
|
|
||||||
QCOMPARE(m_model->parser()->namedQuickTestsCount(), 0);
|
|
||||||
QCOMPARE(m_model->parser()->unnamedQuickTestsCount(), 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Internal
|
} // namespace Internal
|
||||||
|
|||||||
@@ -26,7 +26,6 @@
|
|||||||
#include "autotestconstants.h"
|
#include "autotestconstants.h"
|
||||||
#include "autotest_utils.h"
|
#include "autotest_utils.h"
|
||||||
#include "testcodeparser.h"
|
#include "testcodeparser.h"
|
||||||
#include "testinfo.h"
|
|
||||||
#include "testvisitor.h"
|
#include "testvisitor.h"
|
||||||
|
|
||||||
#include <coreplugin/editormanager/editormanager.h>
|
#include <coreplugin/editormanager/editormanager.h>
|
||||||
@@ -84,7 +83,6 @@ TestCodeParser::TestCodeParser(TestTreeModel *parent)
|
|||||||
|
|
||||||
TestCodeParser::~TestCodeParser()
|
TestCodeParser::~TestCodeParser()
|
||||||
{
|
{
|
||||||
clearCache();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestCodeParser::setState(State state)
|
void TestCodeParser::setState(State state)
|
||||||
@@ -145,7 +143,7 @@ void TestCodeParser::updateTestTree()
|
|||||||
|
|
||||||
m_fullUpdatePostponed = false;
|
m_fullUpdatePostponed = false;
|
||||||
|
|
||||||
clearCache();
|
emit aboutToPerformFullParse();
|
||||||
qCDebug(LOG) << "calling scanForTests (updateTestTree)";
|
qCDebug(LOG) << "calling scanForTests (updateTestTree)";
|
||||||
scanForTests();
|
scanForTests();
|
||||||
}
|
}
|
||||||
@@ -488,7 +486,7 @@ static TestTreeItem *constructGTestTreeItem(const QString &filePath, const GTest
|
|||||||
static bool parsingHasFailed;
|
static bool parsingHasFailed;
|
||||||
|
|
||||||
void performParse(QFutureInterface<void> &futureInterface, const QStringList &list,
|
void performParse(QFutureInterface<void> &futureInterface, const QStringList &list,
|
||||||
const QMap<QString, TestCodeParser::ReferencingInfo> &referencingFiles,
|
const QMap<QString, QString> &referencingFiles,
|
||||||
TestCodeParser *testCodeParser)
|
TestCodeParser *testCodeParser)
|
||||||
{
|
{
|
||||||
int progressValue = 0;
|
int progressValue = 0;
|
||||||
@@ -501,8 +499,9 @@ void performParse(QFutureInterface<void> &futureInterface, const QStringList &li
|
|||||||
if (snapshot.contains(file)) {
|
if (snapshot.contains(file)) {
|
||||||
CPlusPlus::Document::Ptr doc = snapshot.find(file).value();
|
CPlusPlus::Document::Ptr doc = snapshot.find(file).value();
|
||||||
futureInterface.setProgressValue(++progressValue);
|
futureInterface.setProgressValue(++progressValue);
|
||||||
|
const QString &referencingFile = referencingFiles.value(file);
|
||||||
testCodeParser->checkDocumentForTestCode(doc,
|
testCodeParser->checkDocumentForTestCode(doc,
|
||||||
referencingFiles.value(file).referencingFile);
|
list.contains(referencingFile) ? QString() : referencingFile);
|
||||||
} else {
|
} else {
|
||||||
parsingHasFailed |= (CppTools::ProjectFile::classify(file)
|
parsingHasFailed |= (CppTools::ProjectFile::classify(file)
|
||||||
!= CppTools::ProjectFile::Unclassified);
|
!= CppTools::ProjectFile::Unclassified);
|
||||||
@@ -520,10 +519,8 @@ void TestCodeParser::checkDocumentForTestCode(CPlusPlus::Document::Ptr document,
|
|||||||
|
|
||||||
QList<CppTools::ProjectPart::Ptr> projParts = modelManager->projectPart(fileName);
|
QList<CppTools::ProjectPart::Ptr> projParts = modelManager->projectPart(fileName);
|
||||||
if (projParts.size())
|
if (projParts.size())
|
||||||
if (!projParts.at(0)->selectedForBuilding) {
|
if (!projParts.at(0)->selectedForBuilding)
|
||||||
removeTestsIfNecessary(fileName);
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
if (includesQtQuickTest(document, modelManager)) {
|
if (includesQtQuickTest(document, modelManager)) {
|
||||||
handleQtQuickTest(document);
|
handleQtQuickTest(document);
|
||||||
@@ -540,6 +537,8 @@ void TestCodeParser::checkDocumentForTestCode(CPlusPlus::Document::Ptr document,
|
|||||||
if (declaringDoc.isNull())
|
if (declaringDoc.isNull())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
const bool hasReferencingFile = declaringDoc->fileName() != document->fileName();
|
||||||
|
|
||||||
TestVisitor visitor(testCaseName);
|
TestVisitor visitor(testCaseName);
|
||||||
visitor.accept(declaringDoc->globalNamespace());
|
visitor.accept(declaringDoc->globalNamespace());
|
||||||
const QMap<QString, TestCodeLocationAndType> testFunctions = visitor.privateSlots();
|
const QMap<QString, TestCodeLocationAndType> testFunctions = visitor.privateSlots();
|
||||||
@@ -547,14 +546,16 @@ void TestCodeParser::checkDocumentForTestCode(CPlusPlus::Document::Ptr document,
|
|||||||
QMap<QString, TestCodeLocationList> dataTags =
|
QMap<QString, TestCodeLocationList> dataTags =
|
||||||
checkForDataTags(declaringDoc->fileName(), testFunctions);
|
checkForDataTags(declaringDoc->fileName(), testFunctions);
|
||||||
|
|
||||||
if (declaringDoc->fileName() != document->fileName())
|
if (hasReferencingFile)
|
||||||
dataTags.unite(checkForDataTags(document->fileName(), testFunctions));
|
dataTags.unite(checkForDataTags(document->fileName(), testFunctions));
|
||||||
|
|
||||||
TestTreeItem *item = constructTestTreeItem(declaringDoc->fileName(), QString(),
|
TestTreeItem *item = constructTestTreeItem(declaringDoc->fileName(), QString(),
|
||||||
testCaseName, line, column, testFunctions,
|
testCaseName, line, column, testFunctions,
|
||||||
dataTags);
|
dataTags);
|
||||||
|
if (hasReferencingFile)
|
||||||
|
item->setReferencingFile(fileName);
|
||||||
|
|
||||||
updateModelAndCppDocMap(document, declaringDoc->fileName(), item);
|
emit testItemCreated(item, TestTreeModel::AutoTest);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -570,12 +571,8 @@ void TestCodeParser::checkDocumentForTestCode(CPlusPlus::Document::Ptr document,
|
|||||||
// maybe file is only a referenced file
|
// maybe file is only a referenced file
|
||||||
if (!referencingFile.isEmpty()) {
|
if (!referencingFile.isEmpty()) {
|
||||||
CPlusPlus::Snapshot snapshot = modelManager->snapshot();
|
CPlusPlus::Snapshot snapshot = modelManager->snapshot();
|
||||||
if (snapshot.contains(referencingFile)) {
|
if (snapshot.contains(referencingFile))
|
||||||
checkDocumentForTestCode(snapshot.find(referencingFile).value());
|
checkDocumentForTestCode(snapshot.find(referencingFile).value());
|
||||||
} else { // no referencing file too, so this test case is no more a test case
|
|
||||||
m_referencingFiles.remove(fileName);
|
|
||||||
emit testItemsRemoved(fileName, TestTreeModel::AutoTest);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -602,19 +599,28 @@ void TestCodeParser::handleQtQuickTest(CPlusPlus::Document::Ptr document)
|
|||||||
const TestCodeLocationAndType tcLocationAndType = qmlVisitor.testCaseLocation();
|
const TestCodeLocationAndType tcLocationAndType = qmlVisitor.testCaseLocation();
|
||||||
const QMap<QString, TestCodeLocationAndType> testFunctions = qmlVisitor.testFunctions();
|
const QMap<QString, TestCodeLocationAndType> testFunctions = qmlVisitor.testFunctions();
|
||||||
|
|
||||||
|
TestTreeItem *testTreeItem;
|
||||||
if (testCaseName.isEmpty()) {
|
if (testCaseName.isEmpty()) {
|
||||||
updateUnnamedQuickTests(qmlJSDoc->fileName(), cppFileName, testFunctions);
|
testTreeItem = new TestTreeItem(QString(), QString(), TestTreeItem::TestClass);
|
||||||
continue;
|
|
||||||
} // end of handling test cases without name property
|
|
||||||
|
|
||||||
// construct new/modified TestTreeItem
|
foreach (const QString &functionName, testFunctions.keys()) {
|
||||||
TestTreeItem *testTreeItem
|
const TestCodeLocationAndType locationAndType = testFunctions.value(functionName);
|
||||||
= constructTestTreeItem(tcLocationAndType.m_name, cppFileName, testCaseName,
|
TestTreeItem *testFunction = new TestTreeItem(functionName, locationAndType.m_name,
|
||||||
tcLocationAndType.m_line, tcLocationAndType.m_column,
|
locationAndType.m_type);
|
||||||
testFunctions);
|
testFunction->setLine(locationAndType.m_line);
|
||||||
|
testFunction->setColumn(locationAndType.m_column);
|
||||||
|
testFunction->setMainFile(cppFileName);
|
||||||
|
testFunction->setReferencingFile(cppFileName);
|
||||||
|
testTreeItem->appendChild(testFunction);
|
||||||
|
}
|
||||||
|
|
||||||
// update model and internal map
|
} else {
|
||||||
updateModelAndQuickDocMap(qmlJSDoc, cppFileName, testTreeItem);
|
testTreeItem = constructTestTreeItem(tcLocationAndType.m_name, cppFileName,
|
||||||
|
testCaseName, tcLocationAndType.m_line,
|
||||||
|
tcLocationAndType.m_column, testFunctions);
|
||||||
|
testTreeItem->setReferencingFile(cppFileName);
|
||||||
|
}
|
||||||
|
emit testItemCreated(testTreeItem, TestTreeModel::QuickTest);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -629,7 +635,17 @@ void TestCodeParser::handleGTest(const QString &filePath)
|
|||||||
visitor.accept(ast);
|
visitor.accept(ast);
|
||||||
|
|
||||||
QMap<GTestCaseSpec, TestCodeLocationList> result = visitor.gtestFunctions();
|
QMap<GTestCaseSpec, TestCodeLocationList> result = visitor.gtestFunctions();
|
||||||
updateGTests(document, result);
|
QString proFile;
|
||||||
|
const CppTools::CppModelManager *cppMM = CppTools::CppModelManager::instance();
|
||||||
|
QList<CppTools::ProjectPart::Ptr> ppList = cppMM->projectPart(filePath);
|
||||||
|
if (ppList.size())
|
||||||
|
proFile = ppList.at(0)->projectFile;
|
||||||
|
|
||||||
|
foreach (const GTestCaseSpec &testSpec, result.keys()) {
|
||||||
|
TestTreeItem *item = constructGTestTreeItem(filePath, testSpec, proFile,
|
||||||
|
result.value(testSpec));
|
||||||
|
emit testItemCreated(item, TestTreeModel::GoogleTest);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestCodeParser::onCppDocumentUpdated(const CPlusPlus::Document::Ptr &document)
|
void TestCodeParser::onCppDocumentUpdated(const CPlusPlus::Document::Ptr &document)
|
||||||
@@ -672,26 +688,15 @@ void TestCodeParser::onQmlDocumentUpdated(const QmlJS::Document::Ptr &document)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const CPlusPlus::Snapshot snapshot = CppTools::CppModelManager::instance()->snapshot();
|
const CPlusPlus::Snapshot snapshot = CppTools::CppModelManager::instance()->snapshot();
|
||||||
if (m_referencingFiles.contains(fileName)) {
|
QMap<QString, QString> referencingFiles = m_model->referencingFiles();
|
||||||
const ReferencingInfo &refInfo = m_referencingFiles.value(fileName);
|
if (referencingFiles.contains(fileName)) {
|
||||||
if (refInfo.type == TestTreeModel::QuickTest
|
const QString &referencingFile = referencingFiles.value(fileName);
|
||||||
&& snapshot.contains(refInfo.referencingFile)) {
|
if (!referencingFile.isEmpty() && snapshot.contains(referencingFile)) {
|
||||||
if (!refInfo.referencingFile.isEmpty()) {
|
qCDebug(LOG) << "calling scanForTests with cached referencing files"
|
||||||
qCDebug(LOG) << "calling scanForTests with cached referencing files"
|
<< "(onQmlDocumentUpdated)";
|
||||||
<< "(onQmlDocumentUpdated)";
|
scanForTests(QStringList(referencingFile));
|
||||||
scanForTests(QStringList(refInfo.referencingFile));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (m_unnamedQuickDocList.size() == 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// special case of having unnamed TestCases
|
|
||||||
const QString &mainFile = m_model->getMainFileForUnnamedQuickTest(fileName);
|
|
||||||
if (!mainFile.isEmpty() && snapshot.contains(mainFile)) {
|
|
||||||
qCDebug(LOG) << "calling scanForTests with mainfile (onQmlDocumentUpdated)";
|
|
||||||
scanForTests(QStringList(mainFile));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestCodeParser::onStartupProjectChanged(ProjectExplorer::Project *)
|
void TestCodeParser::onStartupProjectChanged(ProjectExplorer::Project *)
|
||||||
@@ -699,7 +704,7 @@ void TestCodeParser::onStartupProjectChanged(ProjectExplorer::Project *)
|
|||||||
if (m_parserState == FullParse || m_parserState == PartialParse) {
|
if (m_parserState == FullParse || m_parserState == PartialParse) {
|
||||||
Core::ProgressManager::instance()->cancelTasks(Constants::TASK_PARSE);
|
Core::ProgressManager::instance()->cancelTasks(Constants::TASK_PARSE);
|
||||||
} else {
|
} else {
|
||||||
clearCache();
|
emit aboutToPerformFullParse();
|
||||||
emitUpdateTestTree();
|
emitUpdateTestTree();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -714,12 +719,6 @@ void TestCodeParser::onProjectPartsUpdated(ProjectExplorer::Project *project)
|
|||||||
emitUpdateTestTree();
|
emitUpdateTestTree();
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestCodeParser::removeFiles(const QStringList &files)
|
|
||||||
{
|
|
||||||
foreach (const QString &file, files)
|
|
||||||
removeTestsIfNecessary(file);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool TestCodeParser::postponed(const QStringList &fileList)
|
bool TestCodeParser::postponed(const QStringList &fileList)
|
||||||
{
|
{
|
||||||
switch (m_parserState) {
|
switch (m_parserState) {
|
||||||
@@ -786,13 +785,20 @@ void TestCodeParser::scanForTests(const QStringList &fileList)
|
|||||||
}
|
}
|
||||||
|
|
||||||
parsingHasFailed = false;
|
parsingHasFailed = false;
|
||||||
|
|
||||||
|
QMap<QString, QString> referencingFiles = m_model->referencingFiles();
|
||||||
if (isSmallChange) { // no need to do this async or should we do this always async?
|
if (isSmallChange) { // no need to do this async or should we do this always async?
|
||||||
|
foreach (const QString &filePath, list)
|
||||||
|
m_model->markForRemoval(filePath);
|
||||||
|
|
||||||
CppTools::CppModelManager *cppMM = CppTools::CppModelManager::instance();
|
CppTools::CppModelManager *cppMM = CppTools::CppModelManager::instance();
|
||||||
CPlusPlus::Snapshot snapshot = cppMM->snapshot();
|
CPlusPlus::Snapshot snapshot = cppMM->snapshot();
|
||||||
foreach (const QString &file, list) {
|
foreach (const QString &file, list) {
|
||||||
if (snapshot.contains(file)) {
|
if (snapshot.contains(file)) {
|
||||||
CPlusPlus::Document::Ptr doc = snapshot.find(file).value();
|
CPlusPlus::Document::Ptr doc = snapshot.find(file).value();
|
||||||
checkDocumentForTestCode(doc, m_referencingFiles.value(file).referencingFile);
|
const QString &referencingFile = referencingFiles.value(file);
|
||||||
|
checkDocumentForTestCode(doc, list.contains(referencingFile) ? QString()
|
||||||
|
: referencingFile);
|
||||||
} else {
|
} else {
|
||||||
parsingHasFailed |= (CppTools::ProjectFile::classify(file)
|
parsingHasFailed |= (CppTools::ProjectFile::classify(file)
|
||||||
!= CppTools::ProjectFile::Unclassified);
|
!= CppTools::ProjectFile::Unclassified);
|
||||||
@@ -802,7 +808,9 @@ void TestCodeParser::scanForTests(const QStringList &fileList)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
QFuture<void> future = Utils::runAsync<void>(&performParse, list, m_referencingFiles, this);
|
m_model->markAllForRemoval();
|
||||||
|
|
||||||
|
QFuture<void> future = Utils::runAsync<void>(&performParse, list, referencingFiles, this);
|
||||||
Core::FutureProgress *progress
|
Core::FutureProgress *progress
|
||||||
= Core::ProgressManager::addTask(future, isFullParse ? tr("Scanning for Tests")
|
= Core::ProgressManager::addTask(future, isFullParse ? tr("Scanning for Tests")
|
||||||
: tr("Refreshing Tests List"),
|
: tr("Refreshing Tests List"),
|
||||||
@@ -813,53 +821,6 @@ void TestCodeParser::scanForTests(const QStringList &fileList)
|
|||||||
emit parsingStarted();
|
emit parsingStarted();
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestCodeParser::clearCache()
|
|
||||||
{
|
|
||||||
m_referencingFiles.clear();
|
|
||||||
m_unnamedQuickDocList.clear();
|
|
||||||
m_gtestDocList.clear();
|
|
||||||
emit cacheCleared();
|
|
||||||
}
|
|
||||||
|
|
||||||
void TestCodeParser::removeTestsIfNecessary(const QString &fileName)
|
|
||||||
{
|
|
||||||
// check if this file was listed before and remove if necessary (switched config,...)
|
|
||||||
if (m_referencingFiles.contains(fileName)
|
|
||||||
&& m_referencingFiles.value(fileName).type == TestTreeModel::AutoTest) {
|
|
||||||
m_referencingFiles.remove(fileName);
|
|
||||||
emit testItemsRemoved(fileName, TestTreeModel::AutoTest);
|
|
||||||
} else if (m_referencingFiles.contains(fileName)
|
|
||||||
&& m_referencingFiles.value(fileName).type == TestTreeModel::GoogleTest) {
|
|
||||||
m_referencingFiles.remove(fileName);
|
|
||||||
emit testItemsRemoved(fileName, TestTreeModel::GoogleTest);
|
|
||||||
} else { // handle Qt Quick Tests
|
|
||||||
QList<QString> toBeRemoved;
|
|
||||||
foreach (const QString &file, m_referencingFiles.keys()) {
|
|
||||||
if (file == fileName
|
|
||||||
&& m_referencingFiles.value(file).type == TestTreeModel::QuickTest) {
|
|
||||||
toBeRemoved.append(file);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
const ReferencingInfo &refInfo = m_referencingFiles.value(file);
|
|
||||||
if (refInfo.type == TestTreeModel::QuickTest && refInfo.referencingFile == fileName)
|
|
||||||
toBeRemoved.append(file);
|
|
||||||
}
|
|
||||||
foreach (const QString &file, toBeRemoved) {
|
|
||||||
m_referencingFiles.remove(file);
|
|
||||||
emit testItemsRemoved(file, TestTreeModel::QuickTest);
|
|
||||||
}
|
|
||||||
// unnamed Quick Tests must be handled separately
|
|
||||||
if (fileName.endsWith(QLatin1String(".qml"))) {
|
|
||||||
removeUnnamedQuickTestsByName(fileName);
|
|
||||||
} else {
|
|
||||||
QSet<QString> filePaths;
|
|
||||||
m_model->qmlFilesForMainFile(fileName, &filePaths);
|
|
||||||
foreach (const QString &file, filePaths)
|
|
||||||
removeUnnamedQuickTestsByName(file);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void TestCodeParser::onTaskStarted(Core::Id type)
|
void TestCodeParser::onTaskStarted(Core::Id type)
|
||||||
{
|
{
|
||||||
if (type == CppTools::Constants::TASK_INDEX)
|
if (type == CppTools::Constants::TASK_INDEX)
|
||||||
@@ -936,175 +897,5 @@ void TestCodeParser::onPartialParsingFinished()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestCodeParser::updateUnnamedQuickTests(const QString &fileName, const QString &mainFile,
|
|
||||||
const QMap<QString, TestCodeLocationAndType> &functions)
|
|
||||||
{
|
|
||||||
// if this test case was named before remove it
|
|
||||||
m_referencingFiles.remove(fileName);
|
|
||||||
emit testItemsRemoved(fileName, TestTreeModel::QuickTest);
|
|
||||||
|
|
||||||
removeUnnamedQuickTestsByName(fileName);
|
|
||||||
foreach (const QString &functionName, functions.keys()) {
|
|
||||||
UnnamedQuickTestInfo info(functionName, fileName);
|
|
||||||
m_unnamedQuickDocList.append(info);
|
|
||||||
}
|
|
||||||
|
|
||||||
emit unnamedQuickTestsUpdated(mainFile, functions);
|
|
||||||
}
|
|
||||||
|
|
||||||
void TestCodeParser::updateModelAndCppDocMap(CPlusPlus::Document::Ptr document,
|
|
||||||
const QString &declaringFile, TestTreeItem *testItem)
|
|
||||||
{
|
|
||||||
const CppTools::CppModelManager *cppMM = CppTools::CppModelManager::instance();
|
|
||||||
const QString fileName = document->fileName();
|
|
||||||
const QString testCaseName = testItem->name();
|
|
||||||
QString proFile;
|
|
||||||
const QList<CppTools::ProjectPart::Ptr> ppList = cppMM->projectPart(fileName);
|
|
||||||
if (ppList.size())
|
|
||||||
proFile = ppList.at(0)->projectFile;
|
|
||||||
|
|
||||||
if (m_referencingFiles.contains(fileName)
|
|
||||||
&& m_referencingFiles.value(fileName).type == TestTreeModel::AutoTest) {
|
|
||||||
QStringList files = { fileName };
|
|
||||||
if (fileName != declaringFile)
|
|
||||||
files << declaringFile;
|
|
||||||
foreach (const QString &file, files) {
|
|
||||||
const bool setReferencingFile = (files.size() == 2 && file == declaringFile);
|
|
||||||
ReferencingInfo testInfo;
|
|
||||||
if (setReferencingFile) {
|
|
||||||
testInfo.referencingFile = fileName;
|
|
||||||
testItem->setReferencingFile(fileName);
|
|
||||||
}
|
|
||||||
testInfo.type = TestTreeModel::AutoTest;
|
|
||||||
m_referencingFiles.insert(file, testInfo);
|
|
||||||
}
|
|
||||||
emit testItemModified(testItem, TestTreeModel::AutoTest, files);
|
|
||||||
} else {
|
|
||||||
if (declaringFile != fileName)
|
|
||||||
testItem->setReferencingFile(fileName);
|
|
||||||
emit testItemCreated(testItem, TestTreeModel::AutoTest);
|
|
||||||
ReferencingInfo testInfo;
|
|
||||||
testInfo.type = TestTreeModel::AutoTest;
|
|
||||||
m_referencingFiles.insert(fileName, testInfo);
|
|
||||||
if (declaringFile != fileName) {
|
|
||||||
testInfo.referencingFile = fileName;
|
|
||||||
m_referencingFiles.insert(declaringFile, testInfo);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void TestCodeParser::updateModelAndQuickDocMap(QmlJS::Document::Ptr document,
|
|
||||||
const QString &referencingFile,
|
|
||||||
TestTreeItem *testItem)
|
|
||||||
{
|
|
||||||
const CppTools::CppModelManager *cppMM = CppTools::CppModelManager::instance();
|
|
||||||
const QString fileName = document->fileName();
|
|
||||||
QString proFile;
|
|
||||||
QList<CppTools::ProjectPart::Ptr> ppList = cppMM->projectPart(referencingFile);
|
|
||||||
if (ppList.size())
|
|
||||||
proFile = ppList.at(0)->projectFile;
|
|
||||||
|
|
||||||
if (m_referencingFiles.contains(fileName)
|
|
||||||
&& m_referencingFiles.value(fileName).type == TestTreeModel::QuickTest) {
|
|
||||||
ReferencingInfo testInfo;
|
|
||||||
testInfo.referencingFile = referencingFile;
|
|
||||||
testInfo.type = TestTreeModel::QuickTest;
|
|
||||||
testItem->setReferencingFile(referencingFile);
|
|
||||||
emit testItemModified(testItem, TestTreeModel::QuickTest, { fileName });
|
|
||||||
m_referencingFiles.insert(fileName, testInfo);
|
|
||||||
} else {
|
|
||||||
// if it was formerly unnamed remove the respective items
|
|
||||||
removeUnnamedQuickTestsByName(fileName);
|
|
||||||
|
|
||||||
const QString &filePath = testItem->filePath();
|
|
||||||
ReferencingInfo testInfo;
|
|
||||||
testInfo.referencingFile = referencingFile;
|
|
||||||
testInfo.type = TestTreeModel::QuickTest;
|
|
||||||
testItem->setReferencingFile(referencingFile);
|
|
||||||
emit testItemCreated(testItem, TestTreeModel::QuickTest);
|
|
||||||
m_referencingFiles.insert(filePath, testInfo);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void TestCodeParser::updateGTests(const CPlusPlus::Document::Ptr &doc,
|
|
||||||
const QMap<GTestCaseSpec, TestCodeLocationList> &tests)
|
|
||||||
{
|
|
||||||
const QString &fileName = doc->fileName();
|
|
||||||
removeGTestsByName(fileName);
|
|
||||||
|
|
||||||
QString proFile;
|
|
||||||
const CppTools::CppModelManager *cppMM = CppTools::CppModelManager::instance();
|
|
||||||
QList<CppTools::ProjectPart::Ptr> ppList = cppMM->projectPart(fileName);
|
|
||||||
if (ppList.size())
|
|
||||||
proFile = ppList.at(0)->projectFile;
|
|
||||||
|
|
||||||
foreach (const GTestCaseSpec &testSpec, tests.keys()) {
|
|
||||||
TestTreeItem *item = constructGTestTreeItem(fileName, testSpec, proFile, tests.value(testSpec));
|
|
||||||
ReferencingInfo testInfo;
|
|
||||||
testInfo.type = TestTreeModel::GoogleTest;
|
|
||||||
|
|
||||||
foreach (const TestCodeLocationAndType &testSet, tests.value(testSpec)) {
|
|
||||||
GTestInfo gtestInfo(testSpec.testCaseName, testSet.m_name, fileName);
|
|
||||||
if (testSet.m_state & TestTreeItem::Disabled)
|
|
||||||
gtestInfo.setEnabled(false);
|
|
||||||
m_gtestDocList.append(gtestInfo);
|
|
||||||
}
|
|
||||||
emit testItemCreated(item, TestTreeModel::GoogleTest);
|
|
||||||
m_referencingFiles.insert(fileName, testInfo);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void TestCodeParser::removeUnnamedQuickTestsByName(const QString &fileName)
|
|
||||||
{
|
|
||||||
for (int i = m_unnamedQuickDocList.size() - 1; i >= 0; --i) {
|
|
||||||
if (m_unnamedQuickDocList.at(i).fileName() == fileName)
|
|
||||||
m_unnamedQuickDocList.removeAt(i);
|
|
||||||
}
|
|
||||||
emit unnamedQuickTestsRemoved(fileName);
|
|
||||||
}
|
|
||||||
|
|
||||||
void TestCodeParser::removeGTestsByName(const QString &fileName)
|
|
||||||
{
|
|
||||||
for (int i = m_gtestDocList.size() - 1; i >= 0; --i)
|
|
||||||
if (m_gtestDocList.at(i).fileName() == fileName)
|
|
||||||
m_gtestDocList.removeAt(i);
|
|
||||||
|
|
||||||
emit gTestsRemoved(fileName);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef WITH_TESTS
|
|
||||||
int TestCodeParser::autoTestsCount() const
|
|
||||||
{
|
|
||||||
int count = 0;
|
|
||||||
foreach (const QString &file, m_referencingFiles.keys()) {
|
|
||||||
const ReferencingInfo &refInfo = m_referencingFiles.value(file);
|
|
||||||
if (refInfo.type == TestTreeModel::AutoTest && refInfo.referencingFile.isEmpty())
|
|
||||||
++count;
|
|
||||||
}
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|
||||||
int TestCodeParser::namedQuickTestsCount() const
|
|
||||||
{
|
|
||||||
int count = 0;
|
|
||||||
foreach (const QString &file, m_referencingFiles.keys()) {
|
|
||||||
const ReferencingInfo &refInfo = m_referencingFiles.value(file);
|
|
||||||
if (refInfo.type == TestTreeModel::QuickTest)
|
|
||||||
++count;
|
|
||||||
}
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|
||||||
int TestCodeParser::unnamedQuickTestsCount() const
|
|
||||||
{
|
|
||||||
return m_unnamedQuickDocList.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
int TestCodeParser::gtestNamesAndSetsCount() const
|
|
||||||
{
|
|
||||||
return m_gtestDocList.size();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
} // namespace Internal
|
} // namespace Internal
|
||||||
} // namespace Autotest
|
} // namespace Autotest
|
||||||
|
|||||||
@@ -44,8 +44,6 @@ namespace Autotest {
|
|||||||
namespace Internal {
|
namespace Internal {
|
||||||
|
|
||||||
struct TestCodeLocationAndType;
|
struct TestCodeLocationAndType;
|
||||||
class UnnamedQuickTestInfo;
|
|
||||||
class GTestInfo;
|
|
||||||
struct GTestCaseSpec;
|
struct GTestCaseSpec;
|
||||||
|
|
||||||
class TestCodeParser : public QObject
|
class TestCodeParser : public QObject
|
||||||
@@ -65,29 +63,9 @@ public:
|
|||||||
State state() const { return m_parserState; }
|
State state() const { return m_parserState; }
|
||||||
void setDirty() { m_dirty = true; }
|
void setDirty() { m_dirty = true; }
|
||||||
|
|
||||||
#ifdef WITH_TESTS
|
|
||||||
int autoTestsCount() const;
|
|
||||||
int namedQuickTestsCount() const;
|
|
||||||
int unnamedQuickTestsCount() const;
|
|
||||||
int gtestNamesAndSetsCount() const;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// FIXME remove me again
|
|
||||||
struct ReferencingInfo
|
|
||||||
{
|
|
||||||
QString referencingFile;
|
|
||||||
TestTreeModel::Type type;
|
|
||||||
};
|
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void cacheCleared();
|
void aboutToPerformFullParse();
|
||||||
void testItemCreated(TestTreeItem *item, TestTreeModel::Type type);
|
void testItemCreated(TestTreeItem *item, TestTreeModel::Type type);
|
||||||
void testItemModified(TestTreeItem *tItem, TestTreeModel::Type type, const QStringList &file);
|
|
||||||
void testItemsRemoved(const QString &filePath, TestTreeModel::Type type);
|
|
||||||
void unnamedQuickTestsUpdated(const QString &mainFile,
|
|
||||||
const QMap<QString, TestCodeLocationAndType> &functions);
|
|
||||||
void unnamedQuickTestsRemoved(const QString &filePath);
|
|
||||||
void gTestsRemoved(const QString &filePath);
|
|
||||||
void parsingStarted();
|
void parsingStarted();
|
||||||
void parsingFinished();
|
void parsingFinished();
|
||||||
void parsingFailed();
|
void parsingFailed();
|
||||||
@@ -105,34 +83,18 @@ public slots:
|
|||||||
void onQmlDocumentUpdated(const QmlJS::Document::Ptr &document);
|
void onQmlDocumentUpdated(const QmlJS::Document::Ptr &document);
|
||||||
void onStartupProjectChanged(ProjectExplorer::Project *);
|
void onStartupProjectChanged(ProjectExplorer::Project *);
|
||||||
void onProjectPartsUpdated(ProjectExplorer::Project *project);
|
void onProjectPartsUpdated(ProjectExplorer::Project *project);
|
||||||
void removeFiles(const QStringList &files);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool postponed(const QStringList &fileList);
|
bool postponed(const QStringList &fileList);
|
||||||
void scanForTests(const QStringList &fileList = QStringList());
|
void scanForTests(const QStringList &fileList = QStringList());
|
||||||
void clearCache();
|
|
||||||
void removeTestsIfNecessary(const QString &fileName);
|
|
||||||
|
|
||||||
void onTaskStarted(Core::Id type);
|
void onTaskStarted(Core::Id type);
|
||||||
void onAllTasksFinished(Core::Id type);
|
void onAllTasksFinished(Core::Id type);
|
||||||
void onFinished();
|
void onFinished();
|
||||||
void onPartialParsingFinished();
|
void onPartialParsingFinished();
|
||||||
void updateUnnamedQuickTests(const QString &fileName, const QString &mainFile,
|
|
||||||
const QMap<QString, TestCodeLocationAndType> &functions);
|
|
||||||
void updateModelAndCppDocMap(CPlusPlus::Document::Ptr document,
|
|
||||||
const QString &declaringFile, TestTreeItem *testItem);
|
|
||||||
void updateModelAndQuickDocMap(QmlJS::Document::Ptr document,
|
|
||||||
const QString &referencingFile, TestTreeItem *testItem);
|
|
||||||
void updateGTests(const CPlusPlus::Document::Ptr &doc,
|
|
||||||
const QMap<GTestCaseSpec, TestCodeLocationList> &tests);
|
|
||||||
void removeUnnamedQuickTestsByName(const QString &fileName);
|
|
||||||
void removeGTestsByName(const QString &fileName);
|
|
||||||
|
|
||||||
TestTreeModel *m_model;
|
TestTreeModel *m_model;
|
||||||
|
|
||||||
QMap<QString, ReferencingInfo> m_referencingFiles;
|
|
||||||
QList<UnnamedQuickTestInfo> m_unnamedQuickDocList;
|
|
||||||
QList<GTestInfo> m_gtestDocList;
|
|
||||||
bool m_codeModelParsing;
|
bool m_codeModelParsing;
|
||||||
bool m_fullUpdatePostponed;
|
bool m_fullUpdatePostponed;
|
||||||
bool m_partialUpdatePostponed;
|
bool m_partialUpdatePostponed;
|
||||||
|
|||||||
@@ -1,46 +0,0 @@
|
|||||||
/****************************************************************************
|
|
||||||
**
|
|
||||||
** Copyright (C) 2016 The Qt Company Ltd.
|
|
||||||
** Contact: https://www.qt.io/licensing/
|
|
||||||
**
|
|
||||||
** This file is part of Qt Creator.
|
|
||||||
**
|
|
||||||
** Commercial License Usage
|
|
||||||
** Licensees holding valid commercial Qt licenses may use this file in
|
|
||||||
** accordance with the commercial license agreement provided with the
|
|
||||||
** Software or, alternatively, in accordance with the terms contained in
|
|
||||||
** a written agreement between you and The Qt Company. For licensing terms
|
|
||||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
|
||||||
** information use the contact form at https://www.qt.io/contact-us.
|
|
||||||
**
|
|
||||||
** GNU General Public License Usage
|
|
||||||
** Alternatively, this file may be used under the terms of the GNU
|
|
||||||
** General Public License version 3 as published by the Free Software
|
|
||||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
|
||||||
** included in the packaging of this file. Please review the following
|
|
||||||
** information to ensure the GNU General Public License requirements will
|
|
||||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
|
||||||
**
|
|
||||||
****************************************************************************/
|
|
||||||
|
|
||||||
#include "testinfo.h"
|
|
||||||
|
|
||||||
namespace Autotest {
|
|
||||||
namespace Internal {
|
|
||||||
|
|
||||||
UnnamedQuickTestInfo::UnnamedQuickTestInfo(const QString &function, const QString &fileName)
|
|
||||||
: m_function(function),
|
|
||||||
m_fileName(fileName)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
GTestInfo::GTestInfo(const QString &caseName, const QString &setName, const QString &file)
|
|
||||||
: m_caseName(caseName),
|
|
||||||
m_setName(setName),
|
|
||||||
m_fileName(file),
|
|
||||||
m_enabled(true)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace Internal
|
|
||||||
} // namespace Autotest
|
|
||||||
@@ -1,73 +0,0 @@
|
|||||||
/****************************************************************************
|
|
||||||
**
|
|
||||||
** Copyright (C) 2016 The Qt Company Ltd.
|
|
||||||
** Contact: https://www.qt.io/licensing/
|
|
||||||
**
|
|
||||||
** This file is part of Qt Creator.
|
|
||||||
**
|
|
||||||
** Commercial License Usage
|
|
||||||
** Licensees holding valid commercial Qt licenses may use this file in
|
|
||||||
** accordance with the commercial license agreement provided with the
|
|
||||||
** Software or, alternatively, in accordance with the terms contained in
|
|
||||||
** a written agreement between you and The Qt Company. For licensing terms
|
|
||||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
|
||||||
** information use the contact form at https://www.qt.io/contact-us.
|
|
||||||
**
|
|
||||||
** GNU General Public License Usage
|
|
||||||
** Alternatively, this file may be used under the terms of the GNU
|
|
||||||
** General Public License version 3 as published by the Free Software
|
|
||||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
|
||||||
** included in the packaging of this file. Please review the following
|
|
||||||
** information to ensure the GNU General Public License requirements will
|
|
||||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
|
||||||
**
|
|
||||||
****************************************************************************/
|
|
||||||
|
|
||||||
#ifndef TESTINFO_H
|
|
||||||
#define TESTINFO_H
|
|
||||||
|
|
||||||
#include <QStringList>
|
|
||||||
|
|
||||||
namespace Autotest {
|
|
||||||
namespace Internal {
|
|
||||||
|
|
||||||
class UnnamedQuickTestInfo {
|
|
||||||
public:
|
|
||||||
explicit UnnamedQuickTestInfo(const QString &function = QString(),
|
|
||||||
const QString& fileName = QString());
|
|
||||||
~UnnamedQuickTestInfo() {}
|
|
||||||
|
|
||||||
const QString function() const { return m_function; }
|
|
||||||
void setFunction(const QString &function) { m_function = function; }
|
|
||||||
const QString fileName() const { return m_fileName; }
|
|
||||||
void setFileName(const QString &fileName) { m_fileName = fileName; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
QString m_function;
|
|
||||||
QString m_fileName;
|
|
||||||
};
|
|
||||||
|
|
||||||
class GTestInfo {
|
|
||||||
public:
|
|
||||||
explicit GTestInfo(const QString &caseName, const QString &setName, const QString &file);
|
|
||||||
|
|
||||||
const QString caseName() const { return m_caseName; }
|
|
||||||
void setCaseName(const QString &caseName) { m_caseName = caseName; }
|
|
||||||
const QString setName() const { return m_setName; }
|
|
||||||
void setSetName(const QString &setName) { m_setName = setName; }
|
|
||||||
const QString fileName() const { return m_fileName; }
|
|
||||||
void setFileName(const QString &fileName) { m_fileName = fileName; }
|
|
||||||
bool isEnabled() const { return m_enabled; }
|
|
||||||
void setEnabled(bool enabled) { m_enabled = enabled; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
QString m_caseName;
|
|
||||||
QString m_setName;
|
|
||||||
QString m_fileName;
|
|
||||||
bool m_enabled;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace Internal
|
|
||||||
} // namespace Autotest
|
|
||||||
|
|
||||||
#endif // TESTINFO_H
|
|
||||||
@@ -86,33 +86,14 @@ TestTreeModel::TestTreeModel(QObject *parent) :
|
|||||||
rootItem()->appendChild(m_quickTestRootItem);
|
rootItem()->appendChild(m_quickTestRootItem);
|
||||||
rootItem()->appendChild(m_googleTestRootItem);
|
rootItem()->appendChild(m_googleTestRootItem);
|
||||||
|
|
||||||
connect(m_parser, &TestCodeParser::cacheCleared, this,
|
connect(m_parser, &TestCodeParser::aboutToPerformFullParse, this,
|
||||||
&TestTreeModel::removeAllTestItems, Qt::QueuedConnection);
|
&TestTreeModel::removeAllTestItems, Qt::QueuedConnection);
|
||||||
connect(m_parser, &TestCodeParser::testItemCreated,
|
connect(m_parser, &TestCodeParser::testItemCreated,
|
||||||
this, &TestTreeModel::addTestTreeItem, Qt::QueuedConnection);
|
this, &TestTreeModel::addTestTreeItem, Qt::QueuedConnection);
|
||||||
connect(m_parser, &TestCodeParser::testItemModified,
|
connect(m_parser, &TestCodeParser::parsingFinished,
|
||||||
this, &TestTreeModel::modifyTestTreeItem, Qt::QueuedConnection);
|
this, &TestTreeModel::sweep, Qt::QueuedConnection);
|
||||||
connect(m_parser, &TestCodeParser::testItemsRemoved,
|
connect(m_parser, &TestCodeParser::parsingFailed,
|
||||||
this, &TestTreeModel::removeTestTreeItems, Qt::QueuedConnection);
|
this, &TestTreeModel::sweep, Qt::QueuedConnection);
|
||||||
connect(m_parser, &TestCodeParser::unnamedQuickTestsUpdated,
|
|
||||||
this, &TestTreeModel::updateUnnamedQuickTest, Qt::QueuedConnection);
|
|
||||||
connect(m_parser, &TestCodeParser::unnamedQuickTestsRemoved,
|
|
||||||
this, &TestTreeModel::removeUnnamedQuickTests, Qt::QueuedConnection);
|
|
||||||
connect(m_parser, &TestCodeParser::gTestsRemoved,
|
|
||||||
this, &TestTreeModel::removeGTests, Qt::QueuedConnection);
|
|
||||||
|
|
||||||
// CppTools::CppModelManagerInterface *cppMM = CppTools::CppModelManagerInterface::instance();
|
|
||||||
// if (cppMM) {
|
|
||||||
// // replace later on by
|
|
||||||
// // cppMM->registerAstProcessor([this](const CplusPlus::Document::Ptr &doc,
|
|
||||||
// // const CPlusPlus::Snapshot &snapshot) {
|
|
||||||
// // checkForQtTestStuff(doc, snapshot);
|
|
||||||
// // });
|
|
||||||
// connect(cppMM, SIGNAL(documentUpdated(CPlusPlus::Document::Ptr)),
|
|
||||||
// this, SLOT(checkForQtTestStuff(CPlusPlus::Document::Ptr)),
|
|
||||||
// Qt::DirectConnection);
|
|
||||||
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static TestTreeModel *m_instance = 0;
|
static TestTreeModel *m_instance = 0;
|
||||||
@@ -148,7 +129,7 @@ void TestTreeModel::enableParsing()
|
|||||||
connect(cppMM, &CppTools::CppModelManager::documentUpdated,
|
connect(cppMM, &CppTools::CppModelManager::documentUpdated,
|
||||||
m_parser, &TestCodeParser::onCppDocumentUpdated, Qt::QueuedConnection);
|
m_parser, &TestCodeParser::onCppDocumentUpdated, Qt::QueuedConnection);
|
||||||
connect(cppMM, &CppTools::CppModelManager::aboutToRemoveFiles,
|
connect(cppMM, &CppTools::CppModelManager::aboutToRemoveFiles,
|
||||||
m_parser, &TestCodeParser::removeFiles, Qt::QueuedConnection);
|
this, &TestTreeModel::removeFiles, Qt::QueuedConnection);
|
||||||
connect(cppMM, &CppTools::CppModelManager::projectPartsUpdated,
|
connect(cppMM, &CppTools::CppModelManager::projectPartsUpdated,
|
||||||
m_parser, &TestCodeParser::onProjectPartsUpdated);
|
m_parser, &TestCodeParser::onProjectPartsUpdated);
|
||||||
|
|
||||||
@@ -156,7 +137,7 @@ void TestTreeModel::enableParsing()
|
|||||||
connect(qmlJsMM, &QmlJS::ModelManagerInterface::documentUpdated,
|
connect(qmlJsMM, &QmlJS::ModelManagerInterface::documentUpdated,
|
||||||
m_parser, &TestCodeParser::onQmlDocumentUpdated, Qt::QueuedConnection);
|
m_parser, &TestCodeParser::onQmlDocumentUpdated, Qt::QueuedConnection);
|
||||||
connect(qmlJsMM, &QmlJS::ModelManagerInterface::aboutToRemoveFiles,
|
connect(qmlJsMM, &QmlJS::ModelManagerInterface::aboutToRemoveFiles,
|
||||||
m_parser, &TestCodeParser::removeFiles, Qt::QueuedConnection);
|
this, &TestTreeModel::removeFiles, Qt::QueuedConnection);
|
||||||
m_connectionsInitialized = true;
|
m_connectionsInitialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -541,38 +522,6 @@ TestConfiguration *TestTreeModel::getTestConfiguration(const TestTreeItem *item)
|
|||||||
return config;
|
return config;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString TestTreeModel::getMainFileForUnnamedQuickTest(const QString &qmlFile) const
|
|
||||||
{
|
|
||||||
const TestTreeItem *unnamed = unnamedQuickTests();
|
|
||||||
const int count = unnamed ? unnamed->childCount() : 0;
|
|
||||||
for (int row = 0; row < count; ++row) {
|
|
||||||
const TestTreeItem *child = unnamed->childItem(row);
|
|
||||||
if (qmlFile == child->filePath())
|
|
||||||
return child->mainFile();
|
|
||||||
}
|
|
||||||
return QString();
|
|
||||||
}
|
|
||||||
|
|
||||||
void TestTreeModel::qmlFilesForMainFile(const QString &mainFile, QSet<QString> *filePaths) const
|
|
||||||
{
|
|
||||||
const TestTreeItem *unnamed = unnamedQuickTests();
|
|
||||||
if (!unnamed)
|
|
||||||
return;
|
|
||||||
for (int row = 0, count = unnamed->childCount(); row < count; ++row) {
|
|
||||||
const TestTreeItem *child = unnamed->childItem(row);
|
|
||||||
if (child->mainFile() == mainFile)
|
|
||||||
filePaths->insert(child->filePath());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
QList<QString> TestTreeModel::getUnnamedQuickTestFunctions() const
|
|
||||||
{
|
|
||||||
const TestTreeItem *unnamed = unnamedQuickTests();
|
|
||||||
if (unnamed)
|
|
||||||
return unnamed->getChildNames();
|
|
||||||
return QList<QString>();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool TestTreeModel::hasUnnamedQuickTests() const
|
bool TestTreeModel::hasUnnamedQuickTests() const
|
||||||
{
|
{
|
||||||
for (int row = 0, count = m_quickTestRootItem->childCount(); row < count; ++row)
|
for (int row = 0, count = m_quickTestRootItem->childCount(); row < count; ++row)
|
||||||
@@ -591,36 +540,11 @@ TestTreeItem *TestTreeModel::unnamedQuickTests() const
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestTreeModel::removeUnnamedQuickTests(const QString &filePath)
|
void TestTreeModel::removeFiles(const QStringList &files)
|
||||||
{
|
{
|
||||||
TestTreeItem *unnamedQT = unnamedQuickTests();
|
foreach (const QString &file, files)
|
||||||
if (!unnamedQT)
|
markForRemoval(file);
|
||||||
return;
|
sweep();
|
||||||
|
|
||||||
for (int childRow = unnamedQT->childCount() - 1; childRow >= 0; --childRow) {
|
|
||||||
TestTreeItem *child = unnamedQT->childItem(childRow);
|
|
||||||
if (filePath == child->filePath())
|
|
||||||
delete takeItem(child);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (unnamedQT->childCount() == 0)
|
|
||||||
delete takeItem(unnamedQT);
|
|
||||||
emit testTreeModelChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
void TestTreeModel::removeGTests(const QString &filePath)
|
|
||||||
{
|
|
||||||
for (int childRow = m_googleTestRootItem->childCount() - 1; childRow >= 0; --childRow) {
|
|
||||||
TestTreeItem *child = m_googleTestRootItem->childItem(childRow);
|
|
||||||
for (int grandChildRow = child->childCount() - 1; grandChildRow >= 0; --grandChildRow) {
|
|
||||||
TestTreeItem *grandChild = child->childItem(grandChildRow);
|
|
||||||
if (filePath == grandChild->filePath())
|
|
||||||
delete takeItem(grandChild);
|
|
||||||
}
|
|
||||||
if (child->childCount() == 0)
|
|
||||||
delete takeItem(child);
|
|
||||||
}
|
|
||||||
emit testTreeModelChanged();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestTreeModel::markAllForRemoval()
|
void TestTreeModel::markAllForRemoval()
|
||||||
@@ -711,80 +635,61 @@ QMap<QString, QString> TestTreeModel::referencingFiles() const
|
|||||||
return finder.referencingFiles();
|
return finder.referencingFiles();
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestTreeModel::addTestTreeItem(TestTreeItem *item, TestTreeModel::Type type)
|
TestTreeItem *TestTreeModel::findTestTreeItemByContent(TestTreeItem *item, TestTreeItem *parent,
|
||||||
|
Type type)
|
||||||
|
{
|
||||||
|
for (int row = 0, count = parent->childCount(); row < count; ++row) {
|
||||||
|
TestTreeItem *current = parent->childItem(row);
|
||||||
|
if (current->name() != item->name())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case AutoTest:
|
||||||
|
if (current->filePath() == item->filePath())
|
||||||
|
return current;
|
||||||
|
break;
|
||||||
|
case QuickTest:
|
||||||
|
if (current->filePath() == item->filePath() && current->mainFile() == item->mainFile())
|
||||||
|
return current;
|
||||||
|
break;
|
||||||
|
case GoogleTest:
|
||||||
|
if (current->type() == item->type())
|
||||||
|
return current;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestTreeModel::addTestTreeItem(TestTreeItem *item, Type type)
|
||||||
{
|
{
|
||||||
TestTreeItem *parent = rootItemForType(type);
|
TestTreeItem *parent = rootItemForType(type);
|
||||||
if (type == TestTreeModel::GoogleTest) {
|
TestTreeItem *toBeUpdated = findTestTreeItemByContent(item, parent, type);
|
||||||
// check if there's already an item with the same test name...
|
const int count = item->childCount();
|
||||||
TestTreeItem *toBeUpdated = 0;
|
if (toBeUpdated) {
|
||||||
for (int row = 0, count = parent->childCount(); row < count; ++row) {
|
if (!toBeUpdated->markedForRemoval()) {
|
||||||
TestTreeItem *current = parent->childItem(row);
|
for (int row = 0; row < count; ++row)
|
||||||
if (current->name() == item->name() && current->type() == item->type()) {
|
toBeUpdated->appendChild(new TestTreeItem(*item->childItem(row)));
|
||||||
toBeUpdated = current;
|
} else {
|
||||||
break;
|
for (int childRow = count - 1; childRow >= 0; --childRow) {
|
||||||
|
TestTreeItem *childItem = item->childItem(childRow);
|
||||||
|
TestTreeItem *origChild = findTestTreeItemByContent(childItem, toBeUpdated, type);
|
||||||
|
if (origChild) {
|
||||||
|
QModelIndex toBeModifiedIndex = indexForItem(origChild);
|
||||||
|
modifyTestSubtree(toBeModifiedIndex, childItem);
|
||||||
|
} else {
|
||||||
|
toBeUpdated->insertChild(qMin(count, toBeUpdated->childCount()),
|
||||||
|
new TestTreeItem(*childItem));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// ...if so we have, to update this one instead of adding a new item
|
delete item;
|
||||||
if (toBeUpdated) {
|
|
||||||
for (int row = 0, count = item->childCount(); row < count; ++row)
|
|
||||||
toBeUpdated->appendChild(new TestTreeItem(*item->childItem(row)));
|
|
||||||
delete item;
|
|
||||||
} else {
|
|
||||||
parent->appendChild(item);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
parent->appendChild(item);
|
parent->appendChild(item);
|
||||||
}
|
}
|
||||||
emit testTreeModelChanged();
|
emit testTreeModelChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestTreeModel::updateUnnamedQuickTest(const QString &mainFile,
|
|
||||||
const QMap<QString, TestCodeLocationAndType> &functions)
|
|
||||||
{
|
|
||||||
if (functions.isEmpty())
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (!hasUnnamedQuickTests())
|
|
||||||
addTestTreeItem(new TestTreeItem(QString(), QString(), TestTreeItem::TestClass), QuickTest);
|
|
||||||
|
|
||||||
TestTreeItem *unnamed = unnamedQuickTests();
|
|
||||||
foreach (const QString &functionName, functions.keys()) {
|
|
||||||
const TestCodeLocationAndType locationAndType = functions.value(functionName);
|
|
||||||
TestTreeItem *testFunction = new TestTreeItem(functionName, locationAndType.m_name,
|
|
||||||
locationAndType.m_type);
|
|
||||||
testFunction->setLine(locationAndType.m_line);
|
|
||||||
testFunction->setColumn(locationAndType.m_column);
|
|
||||||
testFunction->setMainFile(mainFile);
|
|
||||||
unnamed->appendChild(testFunction);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void TestTreeModel::modifyTestTreeItem(TestTreeItem *item, TestTreeModel::Type type, const QStringList &files)
|
|
||||||
{
|
|
||||||
QModelIndex index = rootIndexForType(type);
|
|
||||||
TestTreeItem *parent = rootItemForType(type);
|
|
||||||
if (files.isEmpty()) {
|
|
||||||
if (TestTreeItem *unnamed = unnamedQuickTests()) {
|
|
||||||
if (unnamed == item) // no need to update or delete
|
|
||||||
return;
|
|
||||||
|
|
||||||
index = indexForItem(unnamed);
|
|
||||||
modifyTestSubtree(index, item);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for (int row = 0; row < parent->childCount(); ++row) {
|
|
||||||
if (files.contains(parent->childItem(row)->filePath())) {
|
|
||||||
index = index.child(row, 0);
|
|
||||||
modifyTestSubtree(index, item);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// item was created as temporary, destroy it if it won't get destroyed by its parent
|
|
||||||
if (!item->parent())
|
|
||||||
delete item;
|
|
||||||
}
|
|
||||||
|
|
||||||
void TestTreeModel::removeAllTestItems()
|
void TestTreeModel::removeAllTestItems()
|
||||||
{
|
{
|
||||||
m_autoTestRootItem->removeChildren();
|
m_autoTestRootItem->removeChildren();
|
||||||
@@ -793,21 +698,6 @@ void TestTreeModel::removeAllTestItems()
|
|||||||
emit testTreeModelChanged();
|
emit testTreeModelChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestTreeModel::removeTestTreeItems(const QString &filePath, Type type)
|
|
||||||
{
|
|
||||||
bool removed = false;
|
|
||||||
const TestTreeItem *rootItem = rootItemForType(type);
|
|
||||||
for (int row = rootItem->childCount() - 1; row >= 0; --row) {
|
|
||||||
TestTreeItem *childItem = rootItem->childItem(row);
|
|
||||||
if (filePath == childItem->filePath()) {
|
|
||||||
delete takeItem(childItem);
|
|
||||||
removed = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (removed)
|
|
||||||
emit testTreeModelChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
TestTreeItem *TestTreeModel::rootItemForType(TestTreeModel::Type type)
|
TestTreeItem *TestTreeModel::rootItemForType(TestTreeModel::Type type)
|
||||||
{
|
{
|
||||||
switch (type) {
|
switch (type) {
|
||||||
@@ -821,19 +711,6 @@ TestTreeItem *TestTreeModel::rootItemForType(TestTreeModel::Type type)
|
|||||||
QTC_ASSERT(false, return 0);
|
QTC_ASSERT(false, return 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
QModelIndex TestTreeModel::rootIndexForType(TestTreeModel::Type type)
|
|
||||||
{
|
|
||||||
switch (type) {
|
|
||||||
case AutoTest:
|
|
||||||
return index(0, 0);
|
|
||||||
case QuickTest:
|
|
||||||
return index(1, 0);
|
|
||||||
case GoogleTest:
|
|
||||||
return index(2, 0);
|
|
||||||
}
|
|
||||||
QTC_ASSERT(false, return QModelIndex());
|
|
||||||
}
|
|
||||||
|
|
||||||
void TestTreeModel::modifyTestSubtree(QModelIndex &toBeModifiedIndex, const TestTreeItem *newItem)
|
void TestTreeModel::modifyTestSubtree(QModelIndex &toBeModifiedIndex, const TestTreeItem *newItem)
|
||||||
{
|
{
|
||||||
if (!toBeModifiedIndex.isValid())
|
if (!toBeModifiedIndex.isValid())
|
||||||
|
|||||||
@@ -64,9 +64,6 @@ public:
|
|||||||
QList<TestConfiguration *> getAllTestCases() const;
|
QList<TestConfiguration *> getAllTestCases() const;
|
||||||
QList<TestConfiguration *> getSelectedTests() const;
|
QList<TestConfiguration *> getSelectedTests() const;
|
||||||
TestConfiguration *getTestConfiguration(const TestTreeItem *item) const;
|
TestConfiguration *getTestConfiguration(const TestTreeItem *item) const;
|
||||||
QString getMainFileForUnnamedQuickTest(const QString &qmlFile) const;
|
|
||||||
void qmlFilesForMainFile(const QString &mainFile, QSet<QString> *filePaths) const;
|
|
||||||
QList<QString> getUnnamedQuickTestFunctions() const;
|
|
||||||
bool hasUnnamedQuickTests() const;
|
bool hasUnnamedQuickTests() const;
|
||||||
|
|
||||||
#ifdef WITH_TESTS
|
#ifdef WITH_TESTS
|
||||||
@@ -90,18 +87,14 @@ public slots:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
void addTestTreeItem(TestTreeItem *item, Type type);
|
void addTestTreeItem(TestTreeItem *item, Type type);
|
||||||
void updateUnnamedQuickTest(const QString &mainFile,
|
|
||||||
const QMap<QString, TestCodeLocationAndType> &functions);
|
|
||||||
void modifyTestTreeItem(TestTreeItem *item, Type type, const QStringList &file);
|
|
||||||
void removeAllTestItems();
|
void removeAllTestItems();
|
||||||
void removeTestTreeItems(const QString &filePath, Type type);
|
void removeFiles(const QStringList &files);
|
||||||
void removeUnnamedQuickTests(const QString &filePath);
|
void markForRemoval(const QString &filePath, Type type);
|
||||||
void removeGTests(const QString &filePath);
|
void sweepChildren(TestTreeItem *item);
|
||||||
bool sweepChildren(TestTreeItem *item);
|
TestTreeItem *findTestTreeItemByContent(TestTreeItem *item, TestTreeItem *parent, Type type);
|
||||||
|
|
||||||
TestTreeItem *unnamedQuickTests() const;
|
TestTreeItem *unnamedQuickTests() const;
|
||||||
TestTreeItem *rootItemForType(Type type);
|
TestTreeItem *rootItemForType(Type type);
|
||||||
QModelIndex rootIndexForType(Type type);
|
|
||||||
|
|
||||||
explicit TestTreeModel(QObject *parent = 0);
|
explicit TestTreeModel(QObject *parent = 0);
|
||||||
void modifyTestSubtree(QModelIndex &toBeModifiedIndex, const TestTreeItem *newItem);
|
void modifyTestSubtree(QModelIndex &toBeModifiedIndex, const TestTreeItem *newItem);
|
||||||
|
|||||||
Reference in New Issue
Block a user