From 2bcc21d5987263c595c196db0f9202b0ef68899b Mon Sep 17 00:00:00 2001 From: Marcus Tillmanns Date: Thu, 18 Jul 2024 09:57:25 +0200 Subject: [PATCH] Lua: Guard Hook connections Change-Id: Id30c75093879b92321af864273c6d4ef390cf71a Reviewed-by: hjk --- src/plugins/lua/bindings/hook.cpp | 40 +++++++++++++---------- src/plugins/lua/bindings/textdocument.cpp | 12 ++++--- src/plugins/lua/luaengine.cpp | 20 +++++++----- src/plugins/lua/luaengine.h | 5 +-- 4 files changed, 45 insertions(+), 32 deletions(-) diff --git a/src/plugins/lua/bindings/hook.cpp b/src/plugins/lua/bindings/hook.cpp index 9506c963610..5eb197330ae 100644 --- a/src/plugins/lua/bindings/hook.cpp +++ b/src/plugins/lua/bindings/hook.cpp @@ -12,25 +12,29 @@ namespace Internal { void addHookModule() { - LuaEngine::registerHook("editors.documentOpened", [](const sol::protected_function &func) { - QObject::connect( - Core::EditorManager::instance(), - &Core::EditorManager::documentOpened, - [func](Core::IDocument *document) { - Utils::expected_str res = LuaEngine::void_safe_call(func, document); - QTC_CHECK_EXPECTED(res); - }); - }); + LuaEngine::registerHook( + "editors.documentOpened", [](const sol::protected_function &func, QObject *guard) { + QObject::connect( + Core::EditorManager::instance(), + &Core::EditorManager::documentOpened, + guard, + [func](Core::IDocument *document) { + Utils::expected_str res = LuaEngine::void_safe_call(func, document); + QTC_CHECK_EXPECTED(res); + }); + }); - LuaEngine::registerHook("editors.documentClosed", [](const sol::protected_function &func) { - QObject::connect( - Core::EditorManager::instance(), - &Core::EditorManager::documentClosed, - [func](Core::IDocument *document) { - Utils::expected_str res = LuaEngine::void_safe_call(func, document); - QTC_CHECK_EXPECTED(res); - }); - }); + LuaEngine::registerHook( + "editors.documentClosed", [](const sol::protected_function &func, QObject *guard) { + QObject::connect( + Core::EditorManager::instance(), + &Core::EditorManager::documentClosed, + guard, + [func](Core::IDocument *document) { + Utils::expected_str res = LuaEngine::void_safe_call(func, document); + QTC_CHECK_EXPECTED(res); + }); + }); } } // namespace Internal diff --git a/src/plugins/lua/bindings/textdocument.cpp b/src/plugins/lua/bindings/textdocument.cpp index 82bb440c83c..f1a636d7402 100644 --- a/src/plugins/lua/bindings/textdocument.cpp +++ b/src/plugins/lua/bindings/textdocument.cpp @@ -117,30 +117,33 @@ void addTextDocumentsModule() return documents; }); - LuaEngine::registerHook("editors.text.opened", [](sol::function func) { + LuaEngine::registerHook("editors.text.opened", [](sol::function func, QObject *guard) { QObject::connect( TextDocumentRegistry::instance(), &TextDocumentRegistry::documentOpened, + guard, [func](TextEditor::TextDocument *document) { Utils::expected_str res = LuaEngine::void_safe_call(func, document); QTC_CHECK_EXPECTED(res); }); }); - LuaEngine::registerHook("editors.text.closed", [](sol::function func) { + LuaEngine::registerHook("editors.text.closed", [](sol::function func, QObject *guard) { QObject::connect( TextDocumentRegistry::instance(), &TextDocumentRegistry::documentClosed, + guard, [func](TextEditor::TextDocument *document) { Utils::expected_str res = LuaEngine::void_safe_call(func, document); QTC_CHECK_EXPECTED(res); }); }); - LuaEngine::registerHook("editors.text.contentsChanged", [](sol::function func) { + LuaEngine::registerHook("editors.text.contentsChanged", [](sol::function func, QObject *guard) { QObject::connect( TextDocumentRegistry::instance(), &TextDocumentRegistry::documentContentsChanged, + guard, [func](TextEditor::TextDocument *document, int position, int charsRemoved, int charsAdded) { Utils::expected_str res = LuaEngine::void_safe_call(func, document, position, charsRemoved, charsAdded); @@ -148,10 +151,11 @@ void addTextDocumentsModule() }); }); - LuaEngine::registerHook("editors.text.currentChanged", [](sol::function func) { + LuaEngine::registerHook("editors.text.currentChanged", [](sol::function func, QObject *guard) { QObject::connect( TextDocumentRegistry::instance(), &TextDocumentRegistry::currentDocumentChanged, + guard, [func](TextEditor::TextDocument *document) { Utils::expected_str res = LuaEngine::void_safe_call(func, document); QTC_CHECK_EXPECTED(res); diff --git a/src/plugins/lua/luaengine.cpp b/src/plugins/lua/luaengine.cpp index d0a44da5dc0..98784c67e63 100644 --- a/src/plugins/lua/luaengine.cpp +++ b/src/plugins/lua/luaengine.cpp @@ -51,7 +51,7 @@ public: QHash m_providers; QList> m_autoProviders; - QMap> m_hooks; + QMap> m_hooks; std::unique_ptr m_luaInterface; }; @@ -155,20 +155,22 @@ void LuaEngine::autoRegister(const std::function ®iste instance().d->m_autoProviders.append(registerFunction); } -void LuaEngine::registerHook(QString name, const std::function &hook) +void LuaEngine::registerHook( + QString name, const std::function &hook) { instance().d->m_hooks.insert("." + name, hook); } expected_str LuaEngine::connectHooks( - sol::state_view lua, const sol::table &table, const QString &path) + sol::state_view lua, const sol::table &table, const QString &path, QObject *guard) { qCDebug(logLuaEngine) << "connectHooks called with path: " << path; for (const auto &[k, v] : table) { qCDebug(logLuaEngine) << "Processing key: " << k.as(); if (v.get_type() == sol::type::table) { - return connectHooks(lua, v.as(), QStringList{path, k.as()}.join(".")); + return connectHooks( + lua, v.as(), QStringList{path, k.as()}.join("."), guard); } else if (v.get_type() == sol::type::function) { QString hookName = QStringList{path, k.as()}.join("."); qCDebug(logLuaEngine) << "Connecting function to hook: " << hookName; @@ -176,7 +178,7 @@ expected_str LuaEngine::connectHooks( if (it == d->m_hooks.end()) return make_unexpected(Tr::tr("No hook with the name \"%1\" found.").arg(hookName)); else - it.value()(v.as()); + it.value()(v.as(), guard); } } @@ -255,8 +257,10 @@ expected_str LuaEngine::prepareSetup( return self.name; })); - lua["PluginSpec"] - = ScriptPluginSpec{pluginSpec.name(), appDataPath, std::make_unique()}; + auto guardObject = std::make_unique(); + auto guardObjectPtr = guardObject.get(); + + lua["PluginSpec"] = ScriptPluginSpec{pluginSpec.name(), appDataPath, std::move(guardObject)}; // TODO: only register what the plugin requested for (const auto &[name, func] : d->m_providers.asKeyValueRange()) { @@ -289,7 +293,7 @@ expected_str LuaEngine::prepareSetup( qCDebug(logLuaEngine) << "Hooks table found: " << hookTable.has_value(); if (hookTable) { - auto connectResult = connectHooks(lua, *hookTable, {}); + auto connectResult = connectHooks(lua, *hookTable, {}, guardObjectPtr); if (!connectResult) return make_unexpected(connectResult.error()); } diff --git a/src/plugins/lua/luaengine.h b/src/plugins/lua/luaengine.h index 5dce7c2f531..9bd4d366bce 100644 --- a/src/plugins/lua/luaengine.h +++ b/src/plugins/lua/luaengine.h @@ -60,7 +60,8 @@ public: static void registerProvider(const QString &packageName, const PackageProvider &provider); static void autoRegister(const std::function ®isterFunction); - static void registerHook(QString name, const std::function &hookProvider); + static void registerHook( + QString name, const std::function &hookProvider); static bool isCoroutine(lua_State *state); @@ -115,7 +116,7 @@ public: protected: Utils::expected_str connectHooks( - sol::state_view lua, const sol::table &table, const QString &path); + sol::state_view lua, const sol::table &table, const QString &path, QObject *guard); private: std::unique_ptr d;