Lua: Implement "Project" module

Change-Id: I97dc1295554ad287ed09f72feb8d1765dff39f50
Reviewed-by: hjk <hjk@qt.io>
This commit is contained in:
Marcus Tillmanns
2024-09-18 14:08:36 +02:00
parent bf8cfeb153
commit fb8f59028c
5 changed files with 216 additions and 1 deletions

View File

@@ -1,6 +1,6 @@
add_qtc_plugin(Lua add_qtc_plugin(Lua
PLUGIN_DEPENDS Core PLUGIN_DEPENDS Core
PUBLIC_DEPENDS lua546 sol2 TextEditor PUBLIC_DEPENDS lua546 sol2 TextEditor ProjectExplorer
PUBLIC_DEFINES LUA_AVAILABLE PUBLIC_DEFINES LUA_AVAILABLE
SOURCES SOURCES
bindings/action.cpp bindings/action.cpp
@@ -15,6 +15,7 @@ add_qtc_plugin(Lua
bindings/localsocket.cpp bindings/localsocket.cpp
bindings/macro.cpp bindings/macro.cpp
bindings/messagemanager.cpp bindings/messagemanager.cpp
bindings/project.cpp
bindings/qt.cpp bindings/qt.cpp
bindings/qtcprocess.cpp bindings/qtcprocess.cpp
bindings/settings.cpp bindings/settings.cpp

View File

@@ -0,0 +1,166 @@
// Copyright (C) The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include "../luaengine.h"
#include <projectexplorer/buildmanager.h>
#include <projectexplorer/project.h>
#include <projectexplorer/projectexplorer.h>
#include <projectexplorer/projectexplorerconstants.h>
#include <projectexplorer/projectmanager.h>
#include <projectexplorer/runconfiguration.h>
#include <projectexplorer/runcontrol.h>
#include <projectexplorer/target.h>
#include <utils/commandline.h>
#include <utils/processinterface.h>
using namespace ProjectExplorer;
using namespace Utils;
namespace Lua::Internal {
void setupProjectModule()
{
registerProvider("Project", [](sol::state_view lua) -> sol::object {
const ScriptPluginSpec *pluginSpec = lua.get<ScriptPluginSpec *>("PluginSpec");
QObject *guard = pluginSpec->connectionGuard.get();
sol::table result = lua.create_table();
result.new_usertype<RunConfiguration>(
"RunConfiguration",
sol::no_constructor,
"runnable",
sol::property(&RunConfiguration::runnable));
result.new_usertype<Project>(
"Project",
sol::no_constructor,
"directory",
sol::property(&Project::projectDirectory),
"activeRunConfiguration",
[](Project *project) { return project->activeTarget()->activeRunConfiguration(); });
result["startupProject"] = [] { return ProjectManager::instance()->startupProject(); };
result["canRunStartupProject"] =
[](const QString &mode) -> std::pair<bool, std::variant<QString, sol::lua_nil_t>> {
auto result = ProjectExplorerPlugin::canRunStartupProject(Utils::Id::fromString(mode));
if (result)
return std::make_pair(true, sol::lua_nil);
return std::make_pair(false, result.error());
};
result["runStartupProject"] =
[guard](const sol::optional<ProcessRunData> &runnable) {
auto project = ProjectManager::instance()->startupProject();
if (!project)
throw sol::error("No startup project");
auto runConfiguration = project->activeTarget()->activeRunConfiguration();
if (!runConfiguration)
throw sol::error("No active run configuration");
auto rc = std::make_unique<RunControl>(ProjectExplorer::Constants::NORMAL_RUN_MODE);
rc->copyDataFromRunConfiguration(runConfiguration);
if (runnable) {
rc->setCommandLine(runnable->command);
rc->setWorkingDirectory(runnable->workingDirectory);
rc->setEnvironment(runnable->environment);
}
BuildForRunConfigStatus status = BuildManager::potentiallyBuildForRunConfig(
runConfiguration);
auto startRun = [rc = std::move(rc)]() mutable {
if (!rc->createMainWorker())
return;
ProjectExplorerPlugin::startRunControl(rc.release());
};
if (status == BuildForRunConfigStatus::Building) {
QObject::connect(
BuildManager::instance(),
&BuildManager::buildQueueFinished,
guard,
[startRun = std::move(startRun)](bool success) mutable {
if (success)
startRun();
},
Qt::SingleShotConnection);
} else {
startRun();
}
};
result["RunMode"] = lua.create_table_with(
"Normal", Constants::NORMAL_RUN_MODE, "Debug", Constants::DEBUG_RUN_MODE);
return result;
});
// startupProjectChanged
registerHook("projects.startupProjectChanged", [](sol::function func, QObject *guard) {
QObject::connect(
ProjectManager::instance(),
&ProjectManager::startupProjectChanged,
guard,
[func](ProjectExplorer::Project *project) {
Utils::expected_str<void> res = void_safe_call(func, project);
QTC_CHECK_EXPECTED(res);
});
});
// projectAdded
registerHook("projects.projectAdded", [](sol::function func, QObject *guard) {
QObject::connect(
ProjectManager::instance(),
&ProjectManager::projectAdded,
guard,
[func](ProjectExplorer::Project *project) {
Utils::expected_str<void> res = void_safe_call(func, project);
QTC_CHECK_EXPECTED(res);
});
});
// projectRemoved
registerHook("projects.projectRemoved", [](sol::function func, QObject *guard) {
QObject::connect(
ProjectManager::instance(),
&ProjectManager::projectRemoved,
guard,
[func](ProjectExplorer::Project *project) {
Utils::expected_str<void> res = void_safe_call(func, project);
QTC_CHECK_EXPECTED(res);
});
});
// aboutToRemoveProject
registerHook("projects.aboutToRemoveProject", [](sol::function func, QObject *guard) {
QObject::connect(
ProjectManager::instance(),
&ProjectManager::aboutToRemoveProject,
guard,
[func](ProjectExplorer::Project *project) {
Utils::expected_str<void> res = void_safe_call(func, project);
QTC_CHECK_EXPECTED(res);
});
});
// runActionsUpdated
registerHook("projects.runActionsUpdated", [](sol::function func, QObject *guard) {
QObject::connect(
ProjectExplorerPlugin::instance(),
&ProjectExplorerPlugin::runActionsUpdated,
guard,
[func]() {
Utils::expected_str<void> res = void_safe_call(func);
QTC_CHECK_EXPECTED(res);
});
});
}
} // namespace Lua::Internal

View File

@@ -45,6 +45,7 @@ void setupLocalSocketModule();
void setupMacroModule(); void setupMacroModule();
void setupMessageManagerModule(); void setupMessageManagerModule();
void setupProcessModule(); void setupProcessModule();
void setupProjectModule();
void setupQtModule(); void setupQtModule();
void setupSettingsModule(); void setupSettingsModule();
void setupTextEditorModule(); void setupTextEditorModule();
@@ -263,6 +264,7 @@ public:
setupMacroModule(); setupMacroModule();
setupMessageManagerModule(); setupMessageManagerModule();
setupProcessModule(); setupProcessModule();
setupProjectModule();
setupQtModule(); setupQtModule();
setupSettingsModule(); setupSettingsModule();
setupTextEditorModule(); setupTextEditorModule();

View File

@@ -0,0 +1,38 @@
---@meta Project
local project = {}
---@module 'Utils'
---@enum RunMode
project.RunMode {
Normal = "RunConfiguration.NormalRunMode",
Debug = "RunConfiguration.DebugRunMode",
}
---@class RunConfiguration
---@field runnable ProcessRunData
project.RunConfiguration = {}
---@class Project
---@field directory FilePath The directory of the project.
project.Project = {}
---Returns the active run configuration of the project.
---@return RunConfiguration|nil The active run configuration of the project, or nil if there is no active run configuration.
function project.Project:activeRunConfiguration() end
---Returns the startup project.
---@return Project|nil The startup project, or nil if there is no startup project.
function project.startupProject() end
---Test whether the current startup project can be started using the specified run mode.
---@param runMode RunMode The run mode to test.
---@return boolean True if the current startup project can be started using the specified run mode; otherwise, false.
---@return string|nil If the project cannot be started, a message explaining why; otherwise, nil.
function project.canRunStartupProject(runMode) end
---Starts the active run configuration of the current startup project. It will be build first if necessary.
---@param runnable? ProcessRunData Override the run configuration with the specified runnable.
function project.runStartupProject(runnable) end
return project

View File

@@ -52,6 +52,14 @@ EditorHooks = {}
---@field contentsChanged? function function(document: TextDocument, position: integer, charsRemoved: integer, charsAdded: integer) ---@field contentsChanged? function function(document: TextDocument, position: integer, charsRemoved: integer, charsAdded: integer)
---@field cursorChanged? function function(editor: TextEditor, cursor: MultiTextCursor) ---@field cursorChanged? function function(editor: TextEditor, cursor: MultiTextCursor)
---@class ProjectHooks
---@field startupProjectChanged? function function(project: Project)
---@field projectAdded? function function(project: Project)
---@field projectRemoved? function function(project: Project)
---@field aboutToRemoveProject? function function(project: Project)
---@field runActionsUpdated? function function() Called when Project.canRunStartupProject() might have changed.
---@class Hooks ---@class Hooks
---@field editors? EditorHooks ---@field editors? EditorHooks
---@field projects? ProjectHooks
Hooks = {} Hooks = {}