Lua: Guard Hook connections

Change-Id: Id30c75093879b92321af864273c6d4ef390cf71a
Reviewed-by: hjk <hjk@qt.io>
This commit is contained in:
Marcus Tillmanns
2024-07-18 09:57:25 +02:00
parent 543f8731b4
commit 2bcc21d598
4 changed files with 45 additions and 32 deletions

View File

@@ -12,20 +12,24 @@ namespace Internal {
void addHookModule() void addHookModule()
{ {
LuaEngine::registerHook("editors.documentOpened", [](const sol::protected_function &func) { LuaEngine::registerHook(
"editors.documentOpened", [](const sol::protected_function &func, QObject *guard) {
QObject::connect( QObject::connect(
Core::EditorManager::instance(), Core::EditorManager::instance(),
&Core::EditorManager::documentOpened, &Core::EditorManager::documentOpened,
guard,
[func](Core::IDocument *document) { [func](Core::IDocument *document) {
Utils::expected_str<void> res = LuaEngine::void_safe_call(func, document); Utils::expected_str<void> res = LuaEngine::void_safe_call(func, document);
QTC_CHECK_EXPECTED(res); QTC_CHECK_EXPECTED(res);
}); });
}); });
LuaEngine::registerHook("editors.documentClosed", [](const sol::protected_function &func) { LuaEngine::registerHook(
"editors.documentClosed", [](const sol::protected_function &func, QObject *guard) {
QObject::connect( QObject::connect(
Core::EditorManager::instance(), Core::EditorManager::instance(),
&Core::EditorManager::documentClosed, &Core::EditorManager::documentClosed,
guard,
[func](Core::IDocument *document) { [func](Core::IDocument *document) {
Utils::expected_str<void> res = LuaEngine::void_safe_call(func, document); Utils::expected_str<void> res = LuaEngine::void_safe_call(func, document);
QTC_CHECK_EXPECTED(res); QTC_CHECK_EXPECTED(res);

View File

@@ -117,30 +117,33 @@ void addTextDocumentsModule()
return documents; return documents;
}); });
LuaEngine::registerHook("editors.text.opened", [](sol::function func) { LuaEngine::registerHook("editors.text.opened", [](sol::function func, QObject *guard) {
QObject::connect( QObject::connect(
TextDocumentRegistry::instance(), TextDocumentRegistry::instance(),
&TextDocumentRegistry::documentOpened, &TextDocumentRegistry::documentOpened,
guard,
[func](TextEditor::TextDocument *document) { [func](TextEditor::TextDocument *document) {
Utils::expected_str<void> res = LuaEngine::void_safe_call(func, document); Utils::expected_str<void> res = LuaEngine::void_safe_call(func, document);
QTC_CHECK_EXPECTED(res); QTC_CHECK_EXPECTED(res);
}); });
}); });
LuaEngine::registerHook("editors.text.closed", [](sol::function func) { LuaEngine::registerHook("editors.text.closed", [](sol::function func, QObject *guard) {
QObject::connect( QObject::connect(
TextDocumentRegistry::instance(), TextDocumentRegistry::instance(),
&TextDocumentRegistry::documentClosed, &TextDocumentRegistry::documentClosed,
guard,
[func](TextEditor::TextDocument *document) { [func](TextEditor::TextDocument *document) {
Utils::expected_str<void> res = LuaEngine::void_safe_call(func, document); Utils::expected_str<void> res = LuaEngine::void_safe_call(func, document);
QTC_CHECK_EXPECTED(res); QTC_CHECK_EXPECTED(res);
}); });
}); });
LuaEngine::registerHook("editors.text.contentsChanged", [](sol::function func) { LuaEngine::registerHook("editors.text.contentsChanged", [](sol::function func, QObject *guard) {
QObject::connect( QObject::connect(
TextDocumentRegistry::instance(), TextDocumentRegistry::instance(),
&TextDocumentRegistry::documentContentsChanged, &TextDocumentRegistry::documentContentsChanged,
guard,
[func](TextEditor::TextDocument *document, int position, int charsRemoved, int charsAdded) { [func](TextEditor::TextDocument *document, int position, int charsRemoved, int charsAdded) {
Utils::expected_str<void> res Utils::expected_str<void> res
= LuaEngine::void_safe_call(func, document, position, charsRemoved, charsAdded); = 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( QObject::connect(
TextDocumentRegistry::instance(), TextDocumentRegistry::instance(),
&TextDocumentRegistry::currentDocumentChanged, &TextDocumentRegistry::currentDocumentChanged,
guard,
[func](TextEditor::TextDocument *document) { [func](TextEditor::TextDocument *document) {
Utils::expected_str<void> res = LuaEngine::void_safe_call(func, document); Utils::expected_str<void> res = LuaEngine::void_safe_call(func, document);
QTC_CHECK_EXPECTED(res); QTC_CHECK_EXPECTED(res);

View File

@@ -51,7 +51,7 @@ public:
QHash<QString, LuaEngine::PackageProvider> m_providers; QHash<QString, LuaEngine::PackageProvider> m_providers;
QList<std::function<void(sol::state_view)>> m_autoProviders; QList<std::function<void(sol::state_view)>> m_autoProviders;
QMap<QString, std::function<void(sol::function)>> m_hooks; QMap<QString, std::function<void(sol::function, QObject *)>> m_hooks;
std::unique_ptr<LuaInterfaceImpl> m_luaInterface; std::unique_ptr<LuaInterfaceImpl> m_luaInterface;
}; };
@@ -155,20 +155,22 @@ void LuaEngine::autoRegister(const std::function<void(sol::state_view)> &registe
instance().d->m_autoProviders.append(registerFunction); instance().d->m_autoProviders.append(registerFunction);
} }
void LuaEngine::registerHook(QString name, const std::function<void(sol::function)> &hook) void LuaEngine::registerHook(
QString name, const std::function<void(sol::function, QObject *guard)> &hook)
{ {
instance().d->m_hooks.insert("." + name, hook); instance().d->m_hooks.insert("." + name, hook);
} }
expected_str<void> LuaEngine::connectHooks( expected_str<void> 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; qCDebug(logLuaEngine) << "connectHooks called with path: " << path;
for (const auto &[k, v] : table) { for (const auto &[k, v] : table) {
qCDebug(logLuaEngine) << "Processing key: " << k.as<QString>(); qCDebug(logLuaEngine) << "Processing key: " << k.as<QString>();
if (v.get_type() == sol::type::table) { if (v.get_type() == sol::type::table) {
return connectHooks(lua, v.as<sol::table>(), QStringList{path, k.as<QString>()}.join(".")); return connectHooks(
lua, v.as<sol::table>(), QStringList{path, k.as<QString>()}.join("."), guard);
} else if (v.get_type() == sol::type::function) { } else if (v.get_type() == sol::type::function) {
QString hookName = QStringList{path, k.as<QString>()}.join("."); QString hookName = QStringList{path, k.as<QString>()}.join(".");
qCDebug(logLuaEngine) << "Connecting function to hook: " << hookName; qCDebug(logLuaEngine) << "Connecting function to hook: " << hookName;
@@ -176,7 +178,7 @@ expected_str<void> LuaEngine::connectHooks(
if (it == d->m_hooks.end()) if (it == d->m_hooks.end())
return make_unexpected(Tr::tr("No hook with the name \"%1\" found.").arg(hookName)); return make_unexpected(Tr::tr("No hook with the name \"%1\" found.").arg(hookName));
else else
it.value()(v.as<sol::function>()); it.value()(v.as<sol::function>(), guard);
} }
} }
@@ -255,8 +257,10 @@ expected_str<sol::protected_function> LuaEngine::prepareSetup(
return self.name; return self.name;
})); }));
lua["PluginSpec"] auto guardObject = std::make_unique<QObject>();
= ScriptPluginSpec{pluginSpec.name(), appDataPath, std::make_unique<QObject>()}; auto guardObjectPtr = guardObject.get();
lua["PluginSpec"] = ScriptPluginSpec{pluginSpec.name(), appDataPath, std::move(guardObject)};
// TODO: only register what the plugin requested // TODO: only register what the plugin requested
for (const auto &[name, func] : d->m_providers.asKeyValueRange()) { for (const auto &[name, func] : d->m_providers.asKeyValueRange()) {
@@ -289,7 +293,7 @@ expected_str<sol::protected_function> LuaEngine::prepareSetup(
qCDebug(logLuaEngine) << "Hooks table found: " << hookTable.has_value(); qCDebug(logLuaEngine) << "Hooks table found: " << hookTable.has_value();
if (hookTable) { if (hookTable) {
auto connectResult = connectHooks(lua, *hookTable, {}); auto connectResult = connectHooks(lua, *hookTable, {}, guardObjectPtr);
if (!connectResult) if (!connectResult)
return make_unexpected(connectResult.error()); return make_unexpected(connectResult.error());
} }

View File

@@ -60,7 +60,8 @@ public:
static void registerProvider(const QString &packageName, const PackageProvider &provider); static void registerProvider(const QString &packageName, const PackageProvider &provider);
static void autoRegister(const std::function<void(sol::state_view)> &registerFunction); static void autoRegister(const std::function<void(sol::state_view)> &registerFunction);
static void registerHook(QString name, const std::function<void(sol::function)> &hookProvider); static void registerHook(
QString name, const std::function<void(sol::function, QObject *guard)> &hookProvider);
static bool isCoroutine(lua_State *state); static bool isCoroutine(lua_State *state);
@@ -115,7 +116,7 @@ public:
protected: protected:
Utils::expected_str<void> connectHooks( Utils::expected_str<void> 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: private:
std::unique_ptr<LuaEnginePrivate> d; std::unique_ptr<LuaEnginePrivate> d;