From bbed1896561b2f62449cd4f87ef95459c93d2fa1 Mon Sep 17 00:00:00 2001 From: Jarek Kobus Date: Fri, 12 Jul 2024 15:17:00 +0200 Subject: [PATCH] QmlPreview: Get rid of permanent thread Use TaskTree with AsyncTask instead, on demand. Change-Id: I227858eceef822c4106165c561f8ede56dfb78ca Reviewed-by: hjk --- src/plugins/qmlpreview/qmlpreviewplugin.cpp | 87 +++++++------------ src/plugins/qmlpreview/qmlpreviewplugin.h | 7 -- src/plugins/qmlpreview/qmlpreviewruncontrol.h | 1 + 3 files changed, 33 insertions(+), 62 deletions(-) diff --git a/src/plugins/qmlpreview/qmlpreviewplugin.cpp b/src/plugins/qmlpreview/qmlpreviewplugin.cpp index 65e95d8d53e..3b0f8c281f2 100644 --- a/src/plugins/qmlpreview/qmlpreviewplugin.cpp +++ b/src/plugins/qmlpreview/qmlpreviewplugin.cpp @@ -11,6 +11,8 @@ #include "tests/qmlpreviewplugin_test.h" #endif +#include + #include #include #include @@ -40,10 +42,11 @@ #include #include +#include + #include -#include - +#include #include #include #include @@ -55,22 +58,10 @@ #include using namespace ProjectExplorer; +using namespace Tasking; namespace QmlPreview { -class QmlPreviewParser : public QObject -{ - Q_OBJECT -public: - QmlPreviewParser(); - void parse(const QString &name, const QByteArray &contents, - QmlJS::Dialect::Enum dialect); - -signals: - void success(const QString &changedFile, const QByteArray &contents); - void failure(); -}; - static QByteArray defaultFileLoader(const QString &filename, bool *success) { if (Core::DocumentModel::Entry *entry @@ -119,9 +110,9 @@ public: void checkEditor(); void checkFile(const QString &fileName); void triggerPreview(const QString &changedFile, const QByteArray &contents); + void checkDocument(const QString &name, const QByteArray &contents, QmlJS::Dialect::Enum dialect); QmlPreviewPlugin *q = nullptr; - QThread m_parseThread; QString m_previewedFile; QPointer m_lastEditor; QmlPreviewRunControlList m_runningPreviews; @@ -132,6 +123,8 @@ public: QmlPreviewRunnerSetting m_settings; QmlPreviewRunWorkerFactory runWorkerFactory; + + TaskTreeRunner m_parseRunner; }; QmlPreviewPluginPrivate::QmlPreviewPluginPrivate(QmlPreviewPlugin *parent) @@ -210,13 +203,7 @@ QmlPreviewPluginPrivate::QmlPreviewPluginPrivate(QmlPreviewPlugin *parent) toolBar->insertAction(nullptr, action); }); - m_parseThread.start(); - QmlPreviewParser *parser = new QmlPreviewParser; - parser->moveToThread(&m_parseThread); - connect(&m_parseThread, &QThread::finished, parser, &QObject::deleteLater); - connect(q, &QmlPreviewPlugin::checkDocument, parser, &QmlPreviewParser::parse); connect(q, &QmlPreviewPlugin::previewedFileChanged, this, &QmlPreviewPluginPrivate::checkFile); - connect(parser, &QmlPreviewParser::success, this, &QmlPreviewPluginPrivate::triggerPreview); } QmlPreviewPlugin::~QmlPreviewPlugin() @@ -234,13 +221,6 @@ void QmlPreviewPlugin::initialize() #endif } -ExtensionSystem::IPlugin::ShutdownFlag QmlPreviewPlugin::aboutToShutdown() -{ - d->m_parseThread.quit(); - d->m_parseThread.wait(); - return SynchronousShutdown; -} - QString QmlPreviewPlugin::previewedFile() const { return d->m_previewedFile; @@ -405,7 +385,7 @@ void QmlPreviewPluginPrivate::onEditorAboutToClose(Core::IEditor *editor) void QmlPreviewPluginPrivate::setDirty() { m_dirty = true; - QTimer::singleShot(1000, this, [&](){ + QTimer::singleShot(1000, this, [this] { if (m_dirty && m_lastEditor) { m_dirty = false; checkEditor(); @@ -479,7 +459,7 @@ void QmlPreviewPluginPrivate::checkEditor() dialect = QmlJS::Dialect::QmlQtQuick2Ui; else dialect = QmlJS::Dialect::NoLanguage; - emit q->checkDocument(doc->filePath().toString(), doc->contents(), dialect); + checkDocument(doc->filePath().toString(), doc->contents(), dialect); } void QmlPreviewPluginPrivate::checkFile(const QString &fileName) @@ -491,11 +471,8 @@ void QmlPreviewPluginPrivate::checkFile(const QString &fileName) const QByteArray contents = m_settings.fileLoader(fileName, &success); if (success) { - emit q->checkDocument(fileName, - contents, - QmlJS::ModelManagerInterface::guessLanguageOfFile( - Utils::FilePath::fromUserInput(fileName)) - .dialect()); + checkDocument(fileName, contents, QmlJS::ModelManagerInterface::guessLanguageOfFile( + Utils::FilePath::fromUserInput(fileName)).dialect()); } } @@ -507,29 +484,29 @@ void QmlPreviewPluginPrivate::triggerPreview(const QString &changedFile, const Q emit q->updatePreviews(m_previewedFile, changedFile, contents); } -QmlPreviewParser::QmlPreviewParser() +static void parse(QPromise &promise, const QString &name, const QByteArray &contents, + QmlJS::Dialect::Enum dialect) { - static const int dialectMeta = qRegisterMetaType(); - Q_UNUSED(dialectMeta) + if (!QmlJS::Dialect(dialect).isQmlLikeOrJsLanguage()) + return; + + auto qmljsDoc = QmlJS::Document::create(Utils::FilePath::fromString(name), dialect); + if (promise.isCanceled()) + return; + + qmljsDoc->setSource(QString::fromUtf8(contents)); + if (!qmljsDoc->parse()) + promise.future().cancel(); } -void QmlPreviewParser::parse(const QString &name, const QByteArray &contents, - QmlJS::Dialect::Enum dialect) +void QmlPreviewPluginPrivate::checkDocument(const QString &name, const QByteArray &contents, + QmlJS::Dialect::Enum dialect) { - if (!QmlJS::Dialect(dialect).isQmlLikeOrJsLanguage()) { - emit success(name, contents); - return; - } - - QmlJS::Document::MutablePtr qmljsDoc = QmlJS::Document::create(Utils::FilePath::fromString(name), - dialect); - qmljsDoc->setSource(QString::fromUtf8(contents)); - if (qmljsDoc->parse()) - emit success(name, contents); - else - emit failure(); + const auto onParseSetup = [name, contents, dialect](Utils::Async &async) { + async.setConcurrentCallData(parse, name, contents, dialect); + }; + const auto onParseDone = [this, name, contents] { triggerPreview(name, contents); }; + m_parseRunner.start({Utils::AsyncTask(onParseSetup, onParseDone, CallDoneIf::Success)}); } } // namespace QmlPreview - -#include diff --git a/src/plugins/qmlpreview/qmlpreviewplugin.h b/src/plugins/qmlpreview/qmlpreviewplugin.h index 30f0eb54f40..45bd9652681 100644 --- a/src/plugins/qmlpreview/qmlpreviewplugin.h +++ b/src/plugins/qmlpreview/qmlpreviewplugin.h @@ -6,13 +6,9 @@ #include "qmlpreview_global.h" #include "qmldebugtranslationclient.h" -#include #include #include -#include -#include - namespace Core { class IEditor; } namespace ProjectExplorer { class RunControl; } @@ -50,7 +46,6 @@ public: ~QmlPreviewPlugin() override; void initialize() override; - ShutdownFlag aboutToShutdown() override; QString previewedFile() const; void setPreviewedFile(const QString &previewedFile); @@ -80,8 +75,6 @@ public: void removePreview(ProjectExplorer::RunControl *preview); signals: - void checkDocument(const QString &name, const QByteArray &contents, - QmlJS::Dialect::Enum dialect); void updatePreviews(const QString &previewedFile, const QString &changedFile, const QByteArray &contents); void previewedFileChanged(const QString &previewedFile); diff --git a/src/plugins/qmlpreview/qmlpreviewruncontrol.h b/src/plugins/qmlpreview/qmlpreviewruncontrol.h index 3c9d859c41b..ef3ff417616 100644 --- a/src/plugins/qmlpreview/qmlpreviewruncontrol.h +++ b/src/plugins/qmlpreview/qmlpreviewruncontrol.h @@ -7,6 +7,7 @@ #include #include +#include namespace QmlPreview {