summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--plugins/autotest/autotest.qbs6
-rw-r--r--plugins/autotest/autotest_dependencies.pri8
-rw-r--r--plugins/autotest/autotestunittests.cpp60
-rw-r--r--plugins/autotest/autotestunittests.h2
-rw-r--r--plugins/autotest/autotestunittests.qrc11
-rw-r--r--plugins/autotest/testcodeparser.cpp239
-rw-r--r--plugins/autotest/testcodeparser.h8
-rw-r--r--plugins/autotest/testnavigationwidget.cpp2
-rw-r--r--plugins/autotest/testresultdelegate.cpp5
-rw-r--r--plugins/autotest/testresultdelegate.h4
-rw-r--r--plugins/autotest/testtreemodel.cpp6
-rw-r--r--plugins/autotest/unit_test/mixed_atp/mixed_atp.qbs8
-rw-r--r--plugins/autotest/unit_test/mixed_atp/src/src.qbs11
-rw-r--r--plugins/autotest/unit_test/mixed_atp/tests/auto/auto.qbs13
-rw-r--r--plugins/autotest/unit_test/mixed_atp/tests/auto/bench/bench.qbs14
-rw-r--r--plugins/autotest/unit_test/mixed_atp/tests/auto/dummy/dummy.qbs12
-rw-r--r--plugins/autotest/unit_test/mixed_atp/tests/auto/gui/gui.qbs13
-rw-r--r--plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto/quickauto.qbs33
-rw-r--r--plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto2/quickauto2.qbs29
-rw-r--r--plugins/autotest/unit_test/mixed_atp/tests/tests.qbs7
-rw-r--r--plugins/autotest/unit_test/plain/plain.qbs7
-rw-r--r--plugins/autotest/unit_test/plain/test_plain/test_plain.qbs10
22 files changed, 362 insertions, 146 deletions
diff --git a/plugins/autotest/autotest.qbs b/plugins/autotest/autotest.qbs
index 4a9ec9e4c8..f746d7fae1 100644
--- a/plugins/autotest/autotest.qbs
+++ b/plugins/autotest/autotest.qbs
@@ -7,11 +7,15 @@ QtcCommercialPlugin {
Depends { name: "CppTools" }
Depends { name: "CPlusPlus" }
Depends { name: "ProjectExplorer" }
- Depends { name: "QmakeProjectManager" }
Depends { name: "QmlJS" }
Depends { name: "QmlJSTools" }
Depends { name: "Utils" }
+ pluginTestDepends: [
+ "QbsProjectManager",
+ "QmakeProjectManager"
+ ]
+
Depends {
name: "QtSupport"
condition: project.testsEnabled
diff --git a/plugins/autotest/autotest_dependencies.pri b/plugins/autotest/autotest_dependencies.pri
index 74dc51e15b..9410d77950 100644
--- a/plugins/autotest/autotest_dependencies.pri
+++ b/plugins/autotest/autotest_dependencies.pri
@@ -4,8 +4,7 @@ QTC_PLUGIN_DEPENDS += \
coreplugin \
projectexplorer \
cpptools \
- qmljstools \
- qmakeprojectmanager
+ qmljstools
CONFIG(licensechecker): QTC_PLUGIN_DEPENDS += licensechecker
@@ -14,4 +13,9 @@ QTC_LIB_DEPENDS += \
qmljs \
utils
+QTC_TEST_DEPENDS += \
+ qbsprojectmanager \
+ qmakeprojectmanager \
+ qtsupport
+
#QTC_PLUGIN_RECOMMENDS += \
diff --git a/plugins/autotest/autotestunittests.cpp b/plugins/autotest/autotestunittests.cpp
index 15f32db669..8878f75418 100644
--- a/plugins/autotest/autotestunittests.cpp
+++ b/plugins/autotest/autotestunittests.cpp
@@ -117,6 +117,66 @@ void AutoTestUnitTests::testCodeParser_data()
QTest::newRow("mixedAutoTestAndQuickTests")
<< QString(m_tmpDir->path() + QLatin1String("/mixed_atp/mixed_atp.pro"))
<< 3 << 5 << 3;
+ QTest::newRow("plainAutoTestQbs")
+ << QString(m_tmpDir->path() + QLatin1String("/plain/plain.qbs"))
+ << 1 << 0 << 0;
+ QTest::newRow("mixedAuotTestAndQuickTestsQbs")
+ << QString(m_tmpDir->path() + QLatin1String("/mixed_atp/mixed_atp.qbs"))
+ << 3 << 5 << 3;
+}
+
+void AutoTestUnitTests::testCodeParserSwitchStartup()
+{
+ QFETCH(QStringList, projectFilePaths);
+ QFETCH(QList<int>, expectedAutoTestsCount);
+ QFETCH(QList<int>, expectedNamedQuickTestsCount);
+ QFETCH(QList<int>, expectedUnnamedQuickTestsCount);
+
+ NavigationWidget *navigation = NavigationWidget::instance();
+ navigation->activateSubWidget(Constants::AUTOTEST_ID);
+
+ CppTools::Tests::ProjectOpenerAndCloser projectManager;
+ for (int i = 0; i < projectFilePaths.size(); ++i) {
+ qDebug() << "Opening project" << projectFilePaths.at(i);
+ CppTools::ProjectInfo projectInfo = projectManager.open(projectFilePaths.at(i), true);
+ QVERIFY(projectInfo.isValid());
+
+ QSignalSpy parserSpy(m_model->parser(), SIGNAL(parsingFinished()));
+ QVERIFY(parserSpy.wait(20000));
+
+ QCOMPARE(m_model->autoTestsCount(), expectedAutoTestsCount.at(i));
+ QCOMPARE(m_model->namedQuickTestsCount(),
+ m_isQt4 ? 0 : expectedNamedQuickTestsCount.at(i));
+ QCOMPARE(m_model->unnamedQuickTestsCount(),
+ m_isQt4 ? 0 : expectedUnnamedQuickTestsCount.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));
+ }
+}
+
+void AutoTestUnitTests::testCodeParserSwitchStartup_data()
+{
+ QTest::addColumn<QStringList>("projectFilePaths");
+ QTest::addColumn<QList<int> >("expectedAutoTestsCount");
+ QTest::addColumn<QList<int> >("expectedNamedQuickTestsCount");
+ QTest::addColumn<QList<int> >("expectedUnnamedQuickTestsCount");
+
+ QStringList projects = QStringList()
+ << QString(m_tmpDir->path() + QLatin1String("/plain/plain.pro"))
+ << QString(m_tmpDir->path() + QLatin1String("/mixed_atp/mixed_atp.pro"))
+ << QString(m_tmpDir->path() + QLatin1String("/plain/plain.qbs"))
+ << QString(m_tmpDir->path() + QLatin1String("/mixed_atp/mixed_atp.qbs"));
+
+ QList<int> expectedAutoTests = QList<int>() << 1 << 3 << 1 << 3;
+ QList<int> expectedNamedQuickTests = QList<int>() << 0 << 5 << 0 << 5;
+ QList<int> expectedUnnamedQuickTests = QList<int>() << 0 << 3 << 0 << 3;
+
+ QTest::newRow("loadMultipleProjects")
+ << projects << expectedAutoTests << expectedNamedQuickTests << expectedUnnamedQuickTests;
}
} // namespace Internal
diff --git a/plugins/autotest/autotestunittests.h b/plugins/autotest/autotestunittests.h
index ab2b7c1b9b..e359e4175d 100644
--- a/plugins/autotest/autotestunittests.h
+++ b/plugins/autotest/autotestunittests.h
@@ -43,6 +43,8 @@ private slots:
void cleanupTestCase();
void testCodeParser();
void testCodeParser_data();
+ void testCodeParserSwitchStartup();
+ void testCodeParserSwitchStartup_data();
private:
TestTreeModel *m_model;
diff --git a/plugins/autotest/autotestunittests.qrc b/plugins/autotest/autotestunittests.qrc
index 6fb5348e54..25ce4044fe 100644
--- a/plugins/autotest/autotestunittests.qrc
+++ b/plugins/autotest/autotestunittests.qrc
@@ -28,5 +28,16 @@
<file>unit_test/mixed_atp/tests/auto/quickauto/quickauto.pro</file>
<file>unit_test/mixed_atp/tests/auto/quickauto2/quickauto2.pro</file>
<file>unit_test/mixed_atp/tests/auto/auto.pro</file>
+ <file>unit_test/plain/plain.qbs</file>
+ <file>unit_test/plain/test_plain/test_plain.qbs</file>
+ <file>unit_test/mixed_atp/mixed_atp.qbs</file>
+ <file>unit_test/mixed_atp/src/src.qbs</file>
+ <file>unit_test/mixed_atp/tests/tests.qbs</file>
+ <file>unit_test/mixed_atp/tests/auto/auto.qbs</file>
+ <file>unit_test/mixed_atp/tests/auto/bench/bench.qbs</file>
+ <file>unit_test/mixed_atp/tests/auto/dummy/dummy.qbs</file>
+ <file>unit_test/mixed_atp/tests/auto/gui/gui.qbs</file>
+ <file>unit_test/mixed_atp/tests/auto/quickauto/quickauto.qbs</file>
+ <file>unit_test/mixed_atp/tests/auto/quickauto2/quickauto2.qbs</file>
</qresource>
</RCC>
diff --git a/plugins/autotest/testcodeparser.cpp b/plugins/autotest/testcodeparser.cpp
index 004f733fbd..d01fb3140f 100644
--- a/plugins/autotest/testcodeparser.cpp
+++ b/plugins/autotest/testcodeparser.cpp
@@ -33,11 +33,9 @@
#include <cpptools/cppmodelmanager.h>
#include <cpptools/cppworkingcopy.h>
+#include <projectexplorer/project.h>
#include <projectexplorer/session.h>
-#include <qmakeprojectmanager/qmakeproject.h>
-#include <qmakeprojectmanager/qmakeprojectmanagerconstants.h>
-
#include <qmljs/parser/qmljsast_p.h>
#include <qmljs/qmljsdialect.h>
#include <qmljstools/qmljsmodelmanager.h>
@@ -46,8 +44,13 @@
#include <utils/qtcassert.h>
#include <utils/textfileformat.h>
+#include <QDirIterator>
#include <QFuture>
#include <QFutureInterface>
+#include <QLoggingCategory>
+#include <QTimer>
+
+static Q_LOGGING_CATEGORY(LOG, "qtc.autotest.testcodeparser")
namespace Autotest {
namespace Internal {
@@ -55,10 +58,11 @@ namespace Internal {
TestCodeParser::TestCodeParser(TestTreeModel *parent)
: QObject(parent),
m_model(parent),
- m_parserEnabled(true),
+ m_codeModelParsing(false),
m_fullUpdatePostponed(false),
m_partialUpdatePostponed(false),
- m_dirty(true),
+ m_dirty(false),
+ m_singleShotScheduled(false),
m_parserState(Disabled)
{
// connect to ProgressManager to postpone test parsing when CppModelManager is parsing
@@ -76,61 +80,66 @@ TestCodeParser::~TestCodeParser()
clearCache();
}
-ProjectExplorer::Project *currentProject()
-{
- const ProjectExplorer::SessionManager *session = ProjectExplorer::SessionManager::instance();
- if (!session || !session->hasProjects())
- return 0;
- return session->startupProject();
-}
-
void TestCodeParser::setState(State state)
{
- // avoid triggering parse before code model parsing has finished
- if (!m_parserEnabled)
+ qCDebug(LOG) << "setState(" << state << "), currentState:" << m_parserState;
+ // avoid triggering parse before code model parsing has finished, but mark as dirty
+ if (m_codeModelParsing) {
+ m_dirty = true;
+ qCDebug(LOG) << "Not setting new state - code model parsing is running, just marking dirty";
return;
+ }
if ((state == Disabled || state == Idle)
- && (m_parserState == PartialParse || m_parserState == FullParse))
+ && (m_parserState == PartialParse || m_parserState == FullParse)) {
+ qCDebug(LOG) << "Not setting state, parse is running";
return;
+ }
m_parserState = state;
if (m_parserState == Disabled) {
m_fullUpdatePostponed = m_partialUpdatePostponed = false;
m_postponedFiles.clear();
- } else if (m_parserState == Idle && m_dirty && currentProject()) {
- scanForTests(m_postponedFiles.toList());
+ } else if (m_parserState == Idle && ProjectExplorer::SessionManager::startupProject()) {
+ if (m_fullUpdatePostponed || m_dirty) {
+ emitUpdateTestTree();
+ } else if (m_partialUpdatePostponed) {
+ m_partialUpdatePostponed = false;
+ qCDebug(LOG) << "calling scanForTests with postponed files (setState)";
+ scanForTests(m_postponedFiles.toList());
+ }
}
}
void TestCodeParser::emitUpdateTestTree()
{
+ if (m_singleShotScheduled) {
+ qCDebug(LOG) << "not scheduling another updateTestTree";
+ return;
+ }
+
+ qCDebug(LOG) << "adding singleShot";
+ m_singleShotScheduled = true;
QTimer::singleShot(1000, this, SLOT(updateTestTree()));
}
void TestCodeParser::updateTestTree()
{
- if (!m_parserEnabled) {
+ m_singleShotScheduled = false;
+ if (m_codeModelParsing) {
m_fullUpdatePostponed = true;
+ m_partialUpdatePostponed = false;
+ m_postponedFiles.clear();
return;
}
- if (ProjectExplorer::Project *project = currentProject()) {
- if (auto qmakeProject = qobject_cast<QmakeProjectManager::QmakeProject *>(project)) {
- if (qmakeProject->asyncUpdateState() != QmakeProjectManager::QmakeProject::Base) {
- m_fullUpdatePostponed = true;
- return;
- }
- connect(qmakeProject, &QmakeProjectManager::QmakeProject::proFilesEvaluated,
- this, &TestCodeParser::onProFileEvaluated, Qt::UniqueConnection);
- }
- } else
+ if (!ProjectExplorer::SessionManager::startupProject())
return;
m_fullUpdatePostponed = false;
clearCache();
- emit cacheCleared();
+ qCDebug(LOG) << "calling scanForTests (updateTestTree)";
scanForTests();
}
@@ -370,6 +379,10 @@ static TestTreeItem constructTestTreeItem(const QString &fileName,
/****** end of helpers ******/
+// used internally to indicate a parse that failed due to having triggered a parse for a file that
+// is not (yet) part of the CppModelManager's snapshot
+static bool parsingHasFailed;
+
void performParse(QFutureInterface<void> &futureInterface, QStringList list,
TestCodeParser *testCodeParser)
{
@@ -384,6 +397,9 @@ void performParse(QFutureInterface<void> &futureInterface, QStringList list,
CPlusPlus::Document::Ptr doc = snapshot.find(file).value();
futureInterface.setProgressValue(++progressValue);
testCodeParser->checkDocumentForTestCode(doc);
+ } else {
+ parsingHasFailed |= (CppTools::ProjectFile::classify(file)
+ != CppTools::ProjectFile::Unclassified);
}
}
futureInterface.setProgressValue(list.size());
@@ -482,7 +498,7 @@ void TestCodeParser::handleQtQuickTest(CPlusPlus::Document::Ptr document)
void TestCodeParser::onCppDocumentUpdated(const CPlusPlus::Document::Ptr &document)
{
- if (!m_parserEnabled) {
+ if (m_codeModelParsing) {
if (!m_fullUpdatePostponed) {
m_partialUpdatePostponed = true;
m_postponedFiles.insert(document->fileName());
@@ -490,7 +506,7 @@ void TestCodeParser::onCppDocumentUpdated(const CPlusPlus::Document::Ptr &docume
return;
}
- ProjectExplorer::Project *project = currentProject();
+ ProjectExplorer::Project *project = ProjectExplorer::SessionManager::startupProject();
if (!project)
return;
const QString fileName = document->fileName();
@@ -502,12 +518,13 @@ void TestCodeParser::onCppDocumentUpdated(const CPlusPlus::Document::Ptr &docume
} else if (!project->files(ProjectExplorer::Project::AllFiles).contains(fileName)) {
return;
}
+ qCDebug(LOG) << "calling scanForTests (onCppDocumentUpdated)";
scanForTests(QStringList(fileName));
}
void TestCodeParser::onQmlDocumentUpdated(const QmlJS::Document::Ptr &document)
{
- if (!m_parserEnabled) {
+ if (m_codeModelParsing) {
if (!m_fullUpdatePostponed) {
m_partialUpdatePostponed = true;
m_postponedFiles.insert(document->fileName());
@@ -515,7 +532,7 @@ void TestCodeParser::onQmlDocumentUpdated(const QmlJS::Document::Ptr &document)
return;
}
- ProjectExplorer::Project *project = currentProject();
+ ProjectExplorer::Project *project = ProjectExplorer::SessionManager::startupProject();
if (!project)
return;
const QString fileName = document->fileName();
@@ -530,8 +547,11 @@ void TestCodeParser::onQmlDocumentUpdated(const QmlJS::Document::Ptr &document)
const CPlusPlus::Snapshot snapshot = CppTools::CppModelManager::instance()->snapshot();
if (m_quickDocMap.contains(fileName)
&& snapshot.contains(m_quickDocMap[fileName].referencingFile())) {
- if (!m_quickDocMap[fileName].referencingFile().isEmpty())
+ if (!m_quickDocMap[fileName].referencingFile().isEmpty()) {
+ qCDebug(LOG) << "calling scanForTests with cached referencing files"
+ << "(onQmlDocumentUpdated)";
scanForTests(QStringList(m_quickDocMap[fileName].referencingFile()));
+ }
}
if (m_unnamedQuickDocList.size() == 0)
return;
@@ -539,15 +559,26 @@ void TestCodeParser::onQmlDocumentUpdated(const QmlJS::Document::Ptr &document)
// 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 *)
+{
+ if (m_parserState == FullParse || m_parserState == PartialParse) {
+ Core::ProgressManager::instance()->cancelTasks(Constants::TASK_PARSE);
+ } else {
+ clearCache();
+ emitUpdateTestTree();
+ }
+}
+
void TestCodeParser::onProjectPartsUpdated(ProjectExplorer::Project *project)
{
- if (project != currentProject())
+ if (project != ProjectExplorer::SessionManager::startupProject())
return;
- if (!m_parserEnabled || m_parserState == Disabled)
+ if (m_codeModelParsing || m_parserState == Disabled)
m_fullUpdatePostponed = true;
else
emitUpdateTestTree();
@@ -565,7 +596,8 @@ bool TestCodeParser::postponed(const QStringList &fileList)
case Idle:
return false;
case PartialParse:
- // partial is running, postponing a full parse
+ case FullParse:
+ // parse is running, postponing a full parse
if (fileList.isEmpty()) {
m_partialUpdatePostponed = false;
m_postponedFiles.clear();
@@ -576,23 +608,6 @@ bool TestCodeParser::postponed(const QStringList &fileList)
return true;
// partial parse triggered, postpone or add current files to already postponed partial
foreach (const QString &file, fileList)
- m_postponedFiles.insert(file);
- m_partialUpdatePostponed = true;
- }
- return true;
- case FullParse:
- // full parse is running, postponing another full parse
- if (fileList.isEmpty()) {
- m_partialUpdatePostponed = false;
- m_postponedFiles.clear();
- m_fullUpdatePostponed = true;
- } else {
- // full parse already postponed, ignoring triggering a partial parse
- if (m_fullUpdatePostponed) {
- return true;
- }
- // partial parse triggered, postpone or add current files to already postponed partial
- foreach (const QString &file, fileList)
m_postponedFiles.insert(file);
m_partialUpdatePostponed = true;
}
@@ -624,19 +639,23 @@ void TestCodeParser::scanForTests(const QStringList &fileList)
if (postponed(fileList))
return;
+ m_postponedFiles.clear();
bool isFullParse = fileList.isEmpty();
bool isSmallChange = !isFullParse && fileList.size() < 6;
QStringList list;
if (isFullParse) {
- list = currentProject()->files(ProjectExplorer::Project::AllFiles);
+ list = ProjectExplorer::SessionManager::startupProject()->files(ProjectExplorer::Project::AllFiles);
if (list.isEmpty())
return;
+ qCDebug(LOG) << "setting state to FullParse (scanForTests)";
m_parserState = FullParse;
} else {
list << fileList;
+ qCDebug(LOG) << "setting state to PartialParse (scanForTests)";
m_parserState = PartialParse;
}
+ parsingHasFailed = false;
if (isSmallChange) { // no need to do this async or should we do this always async?
CppTools::CppModelManager *cppMM = CppTools::CppModelManager::instance();
CPlusPlus::Snapshot snapshot = cppMM->snapshot();
@@ -644,9 +663,12 @@ void TestCodeParser::scanForTests(const QStringList &fileList)
if (snapshot.contains(file)) {
CPlusPlus::Document::Ptr doc = snapshot.find(file).value();
checkDocumentForTestCode(doc);
+ } else {
+ parsingHasFailed |= (CppTools::ProjectFile::classify(file)
+ != CppTools::ProjectFile::Unclassified);
}
}
- emit onFinished();
+ onFinished();
return;
}
@@ -666,6 +688,7 @@ void TestCodeParser::clearCache()
m_cppDocMap.clear();
m_quickDocMap.clear();
m_unnamedQuickDocList.clear();
+ emit cacheCleared();
}
void TestCodeParser::removeTestsIfNecessary(const QString &fileName)
@@ -704,39 +727,10 @@ void TestCodeParser::removeTestsIfNecessary(const QString &fileName)
}
}
-void TestCodeParser::removeTestsIfNecessaryByProFile(const QString &proFile)
-{
- QList<QString> fList;
- foreach (const QString &fileName, m_cppDocMap.keys()) {
- if (m_cppDocMap[fileName].proFile() == proFile)
- fList.append(fileName);
- }
- foreach (const QString &fileName, fList) {
- m_cppDocMap.remove(fileName);
- emit testItemsRemoved(fileName, TestTreeModel::AutoTest);
- }
- fList.clear();
- foreach (const QString &fileName, m_quickDocMap.keys()) {
- if (m_quickDocMap[fileName].proFile() == proFile)
- fList.append(fileName);
- }
- foreach (const QString &fileName, fList) {
- m_quickDocMap.remove(fileName);
- emit testItemsRemoved(fileName, TestTreeModel::QuickTest);
- }
- // handle unnamed Quick Tests
- const QSet<QString> &filePaths = m_model->qmlFilesForProFile(proFile);
- foreach (const QString &fileName, filePaths) {
- removeUnnamedQuickTestsByName(fileName);
- emit unnamedQuickTestsRemoved(fileName);
- }
-}
-
void TestCodeParser::onTaskStarted(Core::Id type)
{
- if (type != CppTools::Constants::TASK_INDEX)
- return;
- m_parserEnabled = false;
+ if (type == CppTools::Constants::TASK_INDEX)
+ m_codeModelParsing = true;
}
void TestCodeParser::onAllTasksFinished(Core::Id type)
@@ -744,35 +738,35 @@ void TestCodeParser::onAllTasksFinished(Core::Id type)
// only CPP parsing is relevant as we trigger Qml parsing internally anyway
if (type != CppTools::Constants::TASK_INDEX)
return;
- m_parserEnabled = true;
+ m_codeModelParsing = false;
+
// avoid illegal parser state if respective widgets became hidden while parsing
setState(Idle);
-
- if (m_fullUpdatePostponed)
- updateTestTree();
- else if (m_partialUpdatePostponed) {
- m_partialUpdatePostponed = false;
- QStringList tmp;
- foreach (const QString &file, m_postponedFiles)
- tmp << file;
- m_postponedFiles.clear();
- scanForTests(tmp);
- }
}
void TestCodeParser::onFinished()
{
switch (m_parserState) {
case PartialParse:
+ qCDebug(LOG) << "setting state to Idle (onFinished, PartialParse)";
m_parserState = Idle;
emit partialParsingFinished();
break;
case FullParse:
+ qCDebug(LOG) << "setting state to Idle (onFinished, FullParse)";
m_parserState = Idle;
- emit parsingFinished();
+ m_dirty = parsingHasFailed;
+ if (m_partialUpdatePostponed || m_fullUpdatePostponed || parsingHasFailed) {
+ emit partialParsingFinished();
+ } else {
+ qCDebug(LOG) << "emitting parsingFinished"
+ << "(onFinished, FullParse, nothing postponed, parsing succeeded)";
+ emit parsingFinished();
+ }
m_dirty = false;
break;
case Disabled: // can happen if all Test related widgets become hidden while parsing
+ qCDebug(LOG) << "emitting parsingFinished (onFinished, Disabled)";
emit parsingFinished();
break;
default:
@@ -788,17 +782,24 @@ void TestCodeParser::onPartialParsingFinished()
m_partialUpdatePostponed = false;m_postponedFiles.clear(););
if (m_fullUpdatePostponed) {
m_fullUpdatePostponed = false;
+ qCDebug(LOG) << "calling updateTestTree (onPartialParsingFinished)";
updateTestTree();
} else if (m_partialUpdatePostponed) {
m_partialUpdatePostponed = false;
- QStringList tmp;
- foreach (const QString &file, m_postponedFiles)
- tmp << file;
- m_postponedFiles.clear();
- scanForTests(tmp);
+ qCDebug(LOG) << "calling scanForTests with postponed files (onPartialParsingFinished)";
+ scanForTests(m_postponedFiles.toList());
} else {
- m_dirty = false;
- emit parsingFinished();
+ m_dirty |= m_codeModelParsing;
+ if (m_dirty) {
+ emit parsingFailed();
+ } else if (!m_singleShotScheduled) {
+ qCDebug(LOG) << "emitting parsingFinished"
+ << "(onPartialParsingFinished, nothing postponed, not dirty)";
+ emit parsingFinished();
+ } else {
+ qCDebug(LOG) << "not emitting parsingFinished"
+ << "(on PartialParsingFinished, singleshot scheduled)";
+ }
}
}
@@ -894,28 +895,6 @@ void TestCodeParser::removeUnnamedQuickTestsByName(const QString &fileName)
}
}
-void TestCodeParser::onProFileEvaluated()
-{
- ProjectExplorer::Project *project = currentProject();
- if (!project)
- return;
-
- CppTools::CppModelManager *modelManager = CppTools::CppModelManager::instance();
- const QList<CppTools::ProjectPart::Ptr> pp = modelManager->projectInfo(project).projectParts();
- foreach (const CppTools::ProjectPart::Ptr &p, pp) {
- if (!p->selectedForBuilding)
- removeTestsIfNecessaryByProFile(p->projectFile);
- else {
- QStringList files;
- foreach (auto projectFile, p->files)
- files.append(projectFile.path);
- // avoid illegal parser state when respective widgets became hidden while evaluating
- setState(Idle);
- scanForTests(files);
- }
- }
-}
-
#ifdef WITH_TESTS
int TestCodeParser::autoTestsCount() const
{
diff --git a/plugins/autotest/testcodeparser.h b/plugins/autotest/testcodeparser.h
index 1b8215fe50..5bb54d9320 100644
--- a/plugins/autotest/testcodeparser.h
+++ b/plugins/autotest/testcodeparser.h
@@ -56,6 +56,7 @@ public:
virtual ~TestCodeParser();
void setState(State state);
State state() const { return m_parserState; }
+ void setDirty() { m_dirty = true; }
#ifdef WITH_TESTS
int autoTestsCount() const;
@@ -74,6 +75,7 @@ signals:
void unnamedQuickTestsRemoved(const QString &filePath);
void parsingStarted();
void parsingFinished();
+ void parsingFailed();
void partialParsingFinished();
public slots:
@@ -84,16 +86,15 @@ public slots:
void onCppDocumentUpdated(const CPlusPlus::Document::Ptr &document);
void onQmlDocumentUpdated(const QmlJS::Document::Ptr &document);
+ void onStartupProjectChanged(ProjectExplorer::Project *);
void onProjectPartsUpdated(ProjectExplorer::Project *project);
void removeFiles(const QStringList &files);
- void onProFileEvaluated();
private:
bool postponed(const QStringList &fileList);
void scanForTests(const QStringList &fileList = QStringList());
void clearCache();
void removeTestsIfNecessary(const QString &fileName);
- void removeTestsIfNecessaryByProFile(const QString &proFile);
void onTaskStarted(Core::Id type);
void onAllTasksFinished(Core::Id type);
@@ -111,10 +112,11 @@ private:
QMap<QString, TestInfo> m_cppDocMap;
QMap<QString, TestInfo> m_quickDocMap;
QList<UnnamedQuickTestInfo> m_unnamedQuickDocList;
- bool m_parserEnabled;
+ bool m_codeModelParsing;
bool m_fullUpdatePostponed;
bool m_partialUpdatePostponed;
bool m_dirty;
+ bool m_singleShotScheduled;
QSet<QString> m_postponedFiles;
State m_parserState;
};
diff --git a/plugins/autotest/testnavigationwidget.cpp b/plugins/autotest/testnavigationwidget.cpp
index 9745e1a19b..ad1a496b5f 100644
--- a/plugins/autotest/testnavigationwidget.cpp
+++ b/plugins/autotest/testnavigationwidget.cpp
@@ -75,6 +75,8 @@ TestNavigationWidget::TestNavigationWidget(QWidget *parent) :
this, &TestNavigationWidget::onParsingStarted);
connect(m_model->parser(), &TestCodeParser::parsingFinished,
this, &TestNavigationWidget::onParsingFinished);
+ connect(m_model->parser(), &TestCodeParser::parsingFailed,
+ this, &TestNavigationWidget::onParsingFinished);
connect(m_progressTimer, &QTimer::timeout,
m_progressIndicator, &Utils::ProgressIndicator::show);
}
diff --git a/plugins/autotest/testresultdelegate.cpp b/plugins/autotest/testresultdelegate.cpp
index 5e37c64955..57dc2de847 100644
--- a/plugins/autotest/testresultdelegate.cpp
+++ b/plugins/autotest/testresultdelegate.cpp
@@ -269,11 +269,6 @@ QSize TestResultDelegate::sizeHint(const QStyleOptionViewItem &option, const QMo
return s;
}
-void TestResultDelegate::emitSizeHintChanged(const QModelIndex &index)
-{
- emit sizeHintChanged(index);
-}
-
void TestResultDelegate::currentChanged(const QModelIndex &current, const QModelIndex &previous)
{
emit sizeHintChanged(current);
diff --git a/plugins/autotest/testresultdelegate.h b/plugins/autotest/testresultdelegate.h
index 8bc5d58ad8..0b837ed2b2 100644
--- a/plugins/autotest/testresultdelegate.h
+++ b/plugins/autotest/testresultdelegate.h
@@ -37,10 +37,6 @@ public:
void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const;
QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const;
- void emitSizeHintChanged(const QModelIndex &index);
-
-signals:
-
public slots:
void currentChanged(const QModelIndex &current, const QModelIndex &previous);
diff --git a/plugins/autotest/testtreemodel.cpp b/plugins/autotest/testtreemodel.cpp
index 4639cbd1e9..5eea7b7d98 100644
--- a/plugins/autotest/testtreemodel.cpp
+++ b/plugins/autotest/testtreemodel.cpp
@@ -96,13 +96,17 @@ TestTreeModel::~TestTreeModel()
void TestTreeModel::enableParsing()
{
m_refCounter.ref();
+
+ if (!m_connectionsInitialized)
+ m_parser->setDirty();
+
m_parser->setState(TestCodeParser::Idle);
if (m_connectionsInitialized)
return;
ProjectExplorer::SessionManager *sm = ProjectExplorer::SessionManager::instance();
connect(sm, &ProjectExplorer::SessionManager::startupProjectChanged,
- m_parser, &TestCodeParser::emitUpdateTestTree);
+ m_parser, &TestCodeParser::onStartupProjectChanged);
CppTools::CppModelManager *cppMM = CppTools::CppModelManager::instance();
connect(cppMM, &CppTools::CppModelManager::documentUpdated,
diff --git a/plugins/autotest/unit_test/mixed_atp/mixed_atp.qbs b/plugins/autotest/unit_test/mixed_atp/mixed_atp.qbs
new file mode 100644
index 0000000000..dfc99c15df
--- /dev/null
+++ b/plugins/autotest/unit_test/mixed_atp/mixed_atp.qbs
@@ -0,0 +1,8 @@
+import qbs
+
+Project {
+ references: [
+ "src/src.qbs",
+ "tests/tests.qbs"
+ ]
+}
diff --git a/plugins/autotest/unit_test/mixed_atp/src/src.qbs b/plugins/autotest/unit_test/mixed_atp/src/src.qbs
new file mode 100644
index 0000000000..5ed4dd4a36
--- /dev/null
+++ b/plugins/autotest/unit_test/mixed_atp/src/src.qbs
@@ -0,0 +1,11 @@
+import qbs
+
+CppApplication {
+ type: "application"
+ name: "Dummy Application"
+
+ Depends { name: "Qt.gui" }
+ Depends { name: "Qt.widgets" }
+
+ files: [ "main.cpp" ]
+}
diff --git a/plugins/autotest/unit_test/mixed_atp/tests/auto/auto.qbs b/plugins/autotest/unit_test/mixed_atp/tests/auto/auto.qbs
new file mode 100644
index 0000000000..a27b392244
--- /dev/null
+++ b/plugins/autotest/unit_test/mixed_atp/tests/auto/auto.qbs
@@ -0,0 +1,13 @@
+import qbs
+
+Project {
+ name: "Auto tests"
+
+ references: [
+ "bench/bench.qbs",
+ "dummy/dummy.qbs",
+ "gui/gui.qbs",
+ "quickauto/quickauto.qbs",
+ "quickauto2/quickauto2.qbs"
+ ]
+}
diff --git a/plugins/autotest/unit_test/mixed_atp/tests/auto/bench/bench.qbs b/plugins/autotest/unit_test/mixed_atp/tests/auto/bench/bench.qbs
new file mode 100644
index 0000000000..d10891316a
--- /dev/null
+++ b/plugins/autotest/unit_test/mixed_atp/tests/auto/bench/bench.qbs
@@ -0,0 +1,14 @@
+import qbs
+
+CppApplication {
+ type: "application"
+ name: "Benchmark Auto Test"
+ targetName: "tst_benchtest"
+
+ Depends { name: "cpp" }
+ Depends { name: "Qt.test" }
+
+ files: [ "tst_benchtest.cpp" ]
+
+ cpp.defines: base.concat("SRCDIR=" + path)
+}
diff --git a/plugins/autotest/unit_test/mixed_atp/tests/auto/dummy/dummy.qbs b/plugins/autotest/unit_test/mixed_atp/tests/auto/dummy/dummy.qbs
new file mode 100644
index 0000000000..012ba11a67
--- /dev/null
+++ b/plugins/autotest/unit_test/mixed_atp/tests/auto/dummy/dummy.qbs
@@ -0,0 +1,12 @@
+import qbs
+
+CppApplication {
+ type: "application"
+ name: "Dummy auto test"
+ targetName: "tst_FooBar"
+
+ Depends { name: "Qt.test" }
+ Depends { name: "Qt.gui" }
+
+ files: [ "tst_foo.cpp", "tst_foo.h" ]
+}
diff --git a/plugins/autotest/unit_test/mixed_atp/tests/auto/gui/gui.qbs b/plugins/autotest/unit_test/mixed_atp/tests/auto/gui/gui.qbs
new file mode 100644
index 0000000000..05359cf10f
--- /dev/null
+++ b/plugins/autotest/unit_test/mixed_atp/tests/auto/gui/gui.qbs
@@ -0,0 +1,13 @@
+import qbs
+
+CppApplication {
+ name: "Gui auto test"
+ targetName: "tst_gui"
+
+ Depends { name: "Qt"; submodules: [ "gui", "widgets", "test" ] }
+ Depends { name: "cpp" }
+
+ files: [ "tst_guitest.cpp" ]
+
+ cpp.defines: base.concat("SRCDIR=" + path)
+}
diff --git a/plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto/quickauto.qbs b/plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto/quickauto.qbs
new file mode 100644
index 0000000000..1697cd51a2
--- /dev/null
+++ b/plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto/quickauto.qbs
@@ -0,0 +1,33 @@
+import qbs
+
+CppApplication {
+ name: "Qt Quick auto test"
+ targetName: "test_mal_qtquick"
+
+ Depends { name: "cpp" }
+ Depends { name: "Qt.core" }
+ Depends {
+ condition: Qt.core.versionMajor > 4
+ name: "Qt.qmltest"
+ }
+
+ Group {
+ name: "main application"
+ condition: Qt.core.versionMajor > 4
+
+ files: [ "main.cpp" ]
+ }
+
+ Group {
+ name: "qml test files"
+ qbs.install: true
+
+ files: [
+ "tst_test1.qml", "tst_test2.qml", "TestDummy.qml",
+ "bar/tst_foo.qml", "tst_test3.qml"
+ ]
+ }
+
+ // this should be set automatically, but it seems as if this does not happen
+ cpp.defines: base.concat("QUICK_TEST_SOURCE_DIR=\"" + path + "\"")
+}
diff --git a/plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto2/quickauto2.qbs b/plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto2/quickauto2.qbs
new file mode 100644
index 0000000000..a5fe65fbd6
--- /dev/null
+++ b/plugins/autotest/unit_test/mixed_atp/tests/auto/quickauto2/quickauto2.qbs
@@ -0,0 +1,29 @@
+import qbs
+
+CppApplication {
+ name: "Qt Quick auto test 2"
+ targetName: "test_mal_qtquick"
+
+ Depends { name: "cpp" }
+ Depends { name: "Qt.core" }
+ Depends {
+ condition: Qt.core.versionMajor > 4
+ name: "Qt.qmltest"
+ }
+
+ Group {
+ condition: Qt.core.versionMajor > 4
+ name: "main application"
+ files: [ "main.cpp" ]
+ }
+
+ Group {
+ name: "qml test files"
+ qbs.install: true
+
+ files: [ "tst_test1.qml", "tst_test2.qml" ]
+ }
+
+ // this should be set automatically, but it seems as if this does not happen
+ cpp.defines: base.concat("QUICK_TEST_SOURCE_DIR=\"" + path + "\"")
+}
diff --git a/plugins/autotest/unit_test/mixed_atp/tests/tests.qbs b/plugins/autotest/unit_test/mixed_atp/tests/tests.qbs
new file mode 100644
index 0000000000..e62815789f
--- /dev/null
+++ b/plugins/autotest/unit_test/mixed_atp/tests/tests.qbs
@@ -0,0 +1,7 @@
+import qbs
+
+Project {
+ name: "Tests"
+
+ references: [ "auto/auto.qbs" ]
+}
diff --git a/plugins/autotest/unit_test/plain/plain.qbs b/plugins/autotest/unit_test/plain/plain.qbs
new file mode 100644
index 0000000000..c2fe33618a
--- /dev/null
+++ b/plugins/autotest/unit_test/plain/plain.qbs
@@ -0,0 +1,7 @@
+import qbs
+
+Project {
+ name: "Plain test project"
+
+ references: [ "test_plain/test_plain.qbs" ]
+}
diff --git a/plugins/autotest/unit_test/plain/test_plain/test_plain.qbs b/plugins/autotest/unit_test/plain/test_plain/test_plain.qbs
new file mode 100644
index 0000000000..1b7937ce6a
--- /dev/null
+++ b/plugins/autotest/unit_test/plain/test_plain/test_plain.qbs
@@ -0,0 +1,10 @@
+import qbs
+
+CppApplication {
+ type: "application" // suppress bundle generation on OSX
+
+ Depends { name: "Qt.gui" }
+ Depends { name: "Qt.test" }
+
+ files: [ "tst_simple.cpp", "tst_simple.h" ]
+}