diff --git a/src/plugins/autotest/autotestplugin.cpp b/src/plugins/autotest/autotestplugin.cpp index 05764ab3c25..98b58c0e352 100644 --- a/src/plugins/autotest/autotestplugin.cpp +++ b/src/plugins/autotest/autotestplugin.cpp @@ -154,6 +154,7 @@ void AutotestPlugin::extensionsInitialized() ExtensionSystem::IPlugin::ShutdownFlag AutotestPlugin::aboutToShutdown() { + TestTreeModel::instance()->parser()->aboutToShutdown(); return SynchronousShutdown; } diff --git a/src/plugins/autotest/gtest/gtestparser.cpp b/src/plugins/autotest/gtest/gtestparser.cpp index bf7e8718a1e..2dbe657bf75 100644 --- a/src/plugins/autotest/gtest/gtestparser.cpp +++ b/src/plugins/autotest/gtest/gtestparser.cpp @@ -90,6 +90,8 @@ static bool handleGTest(QFutureInterface futureInterface, const QList &ppList = modelManager->projectPart(filePath); if (ppList.size()) proFile = ppList.first()->projectFile; + else + return false; // happens if shutting down while parsing foreach (const GTestCaseSpec &testSpec, result.keys()) { GTestParseResult *parseResult = new GTestParseResult(id); diff --git a/src/plugins/autotest/qtest/qttestparser.cpp b/src/plugins/autotest/qtest/qttestparser.cpp index 1c273a5e387..b58f192c820 100644 --- a/src/plugins/autotest/qtest/qttestparser.cpp +++ b/src/plugins/autotest/qtest/qttestparser.cpp @@ -199,7 +199,10 @@ static bool handleQtTest(QFutureInterface futureInterface, parseResult->displayName = testCaseName; parseResult->line = line; parseResult->column = column; - parseResult->proFile = modelManager->projectPart(fileName).first()->projectFile; + QList projectParts = modelManager->projectPart(fileName); + if (projectParts.isEmpty()) // happens if shutting down while parsing + return false; + parseResult->proFile = projectParts.first()->projectFile; QMap::ConstIterator it = testFunctions.begin(); const QMap::ConstIterator end = testFunctions.end(); for ( ; it != end; ++it) { diff --git a/src/plugins/autotest/quick/quicktestparser.cpp b/src/plugins/autotest/quick/quicktestparser.cpp index 7c0074ff736..49ad52c6712 100644 --- a/src/plugins/autotest/quick/quicktestparser.cpp +++ b/src/plugins/autotest/quick/quicktestparser.cpp @@ -202,7 +202,8 @@ static bool handleQtQuickTest(QFutureInterface futureInterfa const QString cppFileName = document->fileName(); QList ppList = modelManager->projectPart(cppFileName); - QTC_ASSERT(!ppList.isEmpty(), return false); + if (ppList.isEmpty()) // happens if shutting down while parsing + return false; const QString &proFile = ppList.at(0)->projectFile; const QString srcDir = quickTestSrcDir(modelManager, cppFileName); diff --git a/src/plugins/autotest/testcodeparser.cpp b/src/plugins/autotest/testcodeparser.cpp index 2680736e767..a86ec254e62 100644 --- a/src/plugins/autotest/testcodeparser.cpp +++ b/src/plugins/autotest/testcodeparser.cpp @@ -85,6 +85,8 @@ TestCodeParser::~TestCodeParser() void TestCodeParser::setState(State state) { + if (m_parserState == Shutdown) + return; qCDebug(LOG) << "setState(" << state << "), currentState:" << m_parserState; // avoid triggering parse before code model parsing has finished, but mark as dirty if (m_codeModelParsing) { @@ -175,6 +177,8 @@ static bool checkDocumentForTestCode(QFutureInterface &futur const QVector &parsers) { foreach (ITestParser *currentParser, parsers) { + if (futureInterface.isCanceled()) + return false; if (currentParser->processDocument(futureInterface, fileName)) return true; } @@ -253,6 +257,17 @@ void TestCodeParser::onProjectPartsUpdated(ProjectExplorer::Project *project) emitUpdateTestTree(); } +void TestCodeParser::aboutToShutdown() +{ + qCDebug(LOG) << "Disabling (immediately) - shutting down"; + State oldState = m_parserState; + m_parserState = Shutdown; + if (oldState == PartialParse || oldState == FullParse) { + m_futureWatcher.cancel(); + m_futureWatcher.waitForFinished(); + } +} + bool TestCodeParser::postponed(const QStringList &fileList) { switch (m_parserState) { @@ -278,6 +293,7 @@ bool TestCodeParser::postponed(const QStringList &fileList) } return true; case Disabled: + case Shutdown: break; } QTC_ASSERT(false, return false); // should not happen at all @@ -285,7 +301,7 @@ bool TestCodeParser::postponed(const QStringList &fileList) void TestCodeParser::scanForTests(const QStringList &fileList) { - if (m_parserState == Disabled) { + if (m_parserState == Disabled || m_parserState == Shutdown) { m_dirty = true; if (fileList.isEmpty()) { m_fullUpdatePostponed = true; @@ -390,6 +406,9 @@ void TestCodeParser::onFinished() qCDebug(LOG) << "emitting parsingFinished (onFinished, Disabled)"; emit parsingFinished(); break; + case Shutdown: + qCDebug(LOG) << "Shutdown complete - not emitting parsingFinished (onFinished)"; + break; default: qWarning("I should not be here... State: %d", m_parserState); break; diff --git a/src/plugins/autotest/testcodeparser.h b/src/plugins/autotest/testcodeparser.h index d9779525f8a..ac095c14aac 100644 --- a/src/plugins/autotest/testcodeparser.h +++ b/src/plugins/autotest/testcodeparser.h @@ -48,7 +48,8 @@ public: Idle, PartialParse, FullParse, - Disabled + Disabled, + Shutdown }; explicit TestCodeParser(TestTreeModel *parent = 0); @@ -77,6 +78,7 @@ public: void onQmlDocumentUpdated(const QmlJS::Document::Ptr &document); void onStartupProjectChanged(ProjectExplorer::Project *project); void onProjectPartsUpdated(ProjectExplorer::Project *project); + void aboutToShutdown(); private: bool postponed(const QStringList &fileList);