From 80ab7713f51c60255405a9eaf12edd603f851fc5 Mon Sep 17 00:00:00 2001 From: David Nikdel <556630+ogapo@users.noreply.github.com> Date: Sat, 16 Aug 2025 20:54:10 -0400 Subject: [PATCH 1/2] added ability to specify platform-specific editorPath - support config of the form `godotTools.editorPath.(windows|macos|linux)-(x86_64|arm64).godot(3|4)` - match godot's buildsystem terms for familiarity - expand ${env:X} into the string. Previous code replaced the whole string if it contained an env tag and only matched the first one. - move all path manipulation hacks into clean_godot_path - tried to make sure all code that needs the editor path consistently use the util functions --- package.json | 34 ++++++- src/debugger/godot3/server_controller.ts | 11 ++- src/debugger/godot4/server_controller.ts | 12 +-- .../variables/debugger_variables.test.ts | 7 +- src/extension.ts | 13 ++- src/lsp/ClientConnectionManager.ts | 5 +- src/utils/godot_utils.ts | 99 +++++++++++++------ 7 files changed, 124 insertions(+), 57 deletions(-) diff --git a/package.json b/package.json index 7b7ee3bee..1fb21499b 100644 --- a/package.json +++ b/package.json @@ -272,12 +272,42 @@ "godotTools.editorPath.godot3": { "type": "string", "default": "godot3", - "description": "Path to the Godot 3 editor executable. Supports environment variables using '${env:VAR_NAME}'." + "description": "Path to the Godot 3 editor executable. Workspace relative. Supports environment variables using '${env:VAR_NAME}'." }, "godotTools.editorPath.godot4": { "type": "string", "default": "godot", - "description": "Path to the Godot 4 editor executable. Supports environment variables using '${env:VAR_NAME}'." + "description": "Path to the Godot 4 editor executable. Workspace relative. Supports environment variables using '${env:VAR_NAME}'." + }, + "godotTools.editorPath.windows-arm64.godot4": { + "type": "string", + "default": "", + "description": "Platform-specific editor path. If specified, overrides `godotTools.editorPath.godot4`." + }, + "godotTools.editorPath.macos-arm64.godot4": { + "type": "string", + "default": "", + "description": "Platform-specific editor path. If specified, overrides `godotTools.editorPath.godot4`." + }, + "godotTools.editorPath.linux-arm64.godot4": { + "type": "string", + "default": "", + "description": "Platform-specific editor path. If specified, overrides `godotTools.editorPath.godot4`." + }, + "godotTools.editorPath.windows-x86_64.godot4": { + "type": "string", + "default": "", + "description": "Platform-specific editor path. If specified, overrides `godotTools.editorPath.godot4`." + }, + "godotTools.editorPath.macos-x86_64.godot4": { + "type": "string", + "default": "", + "description": "Platform-specific editor path. If specified, overrides `godotTools.editorPath.godot4`." + }, + "godotTools.editorPath.linux-x86_64.godot4": { + "type": "string", + "default": "", + "description": "Platform-specific editor path. If specified, overrides `godotTools.editorPath.godot4`." }, "godotTools.editor.verbose": { "type": "boolean", diff --git a/src/debugger/godot3/server_controller.ts b/src/debugger/godot3/server_controller.ts index 109c8deb1..bd2ed2534 100644 --- a/src/debugger/godot3/server_controller.ts +++ b/src/debugger/godot3/server_controller.ts @@ -12,7 +12,9 @@ import { get_free_port, get_project_version, verify_godot_version, + clean_godot_path, VERIFY_RESULT, + get_editor_path, } from "../../utils"; import { prompt_for_godot_executable } from "../../utils/prompts"; import { killSubProcesses, subProcess } from "../../utils/subspawn"; @@ -115,9 +117,9 @@ export class ServerController { if (args.editor_path) { log.info("Using 'editor_path' variable from launch.json"); - log.info(`Verifying version of '${args.editor_path}'`); - result = verify_godot_version(args.editor_path, "3"); - godotPath = result.godotPath; + godotPath = clean_godot_path(args.editor_path); + log.info(`Verifying version of '${godotPath}'`); + result = verify_godot_version(godotPath, "3"); log.info(`Verification result: ${result.status}, version: "${result.version}"`); switch (result.status) { @@ -144,11 +146,10 @@ export class ServerController { log.info("Using 'editorPath.godot3' from settings"); const settingName = "editorPath.godot3"; - godotPath = get_configuration(settingName); + godotPath = get_editor_path("3"); log.info(`Verifying version of '${godotPath}'`); result = verify_godot_version(godotPath, "3"); - godotPath = result.godotPath; log.info(`Verification result: ${result.status}, version: "${result.version}"`); switch (result.status) { diff --git a/src/debugger/godot4/server_controller.ts b/src/debugger/godot4/server_controller.ts index 144afbb70..912d7fc1e 100644 --- a/src/debugger/godot4/server_controller.ts +++ b/src/debugger/godot4/server_controller.ts @@ -9,10 +9,11 @@ import { ansi, convert_resource_path_to_uri, createLogger, - get_configuration, get_free_port, get_project_version, verify_godot_version, + clean_godot_path, + get_editor_path, } from "../../utils"; import { prompt_for_godot_executable } from "../../utils/prompts"; import { killSubProcesses, subProcess } from "../../utils/subspawn"; @@ -157,9 +158,9 @@ export class ServerController { if (args.editor_path) { log.info("Using 'editor_path' variable from launch.json"); - log.info(`Verifying version of '${args.editor_path}'`); - result = verify_godot_version(args.editor_path, "4"); - godotPath = result.godotPath; + godotPath = clean_godot_path(args.editor_path); + log.info(`Verifying version of '${godotPath}'`); + result = verify_godot_version(godotPath, "4"); log.info(`Verification result: ${result.status}, version: "${result.version}"`); switch (result.status) { @@ -186,11 +187,10 @@ export class ServerController { log.info("Using 'editorPath.godot4' from settings"); const settingName = "editorPath.godot4"; - godotPath = get_configuration(settingName); + godotPath = get_editor_path("4"); log.info(`Verifying version of '${godotPath}'`); result = verify_godot_version(godotPath, "4"); - godotPath = result.godotPath; log.info(`Verification result: ${result.status}, version: "${result.version}"`); switch (result.status) { diff --git a/src/debugger/godot4/variables/debugger_variables.test.ts b/src/debugger/godot4/variables/debugger_variables.test.ts index 16a8601e0..2ca988d48 100644 --- a/src/debugger/godot4/variables/debugger_variables.test.ts +++ b/src/debugger/godot4/variables/debugger_variables.test.ts @@ -13,7 +13,7 @@ chaiAsPromised.then((module) => { import { promisify } from "node:util"; import { execFile } from "node:child_process"; -import { clean_godot_path } from "../../../utils"; +import { get_editor_path } from "../../../utils"; const execFileAsync = promisify(execFile); @@ -226,10 +226,7 @@ suite("DAP Integration Tests - Variable Scopes", () => { } // init the godot project by importing it in godot engine: - const config = vscode.workspace.getConfiguration("godotTools"); - // config.update("editorPath.godot4", "godot4", vscode.ConfigurationTarget.Workspace); - - const godot4_path = clean_godot_path(config.get("editorPath.godot4")); + const godot4_path = get_editor_path("4"); // get the path for currently opened project in vscode test instance: console.log("Executing", [godot4_path, "--headless", "--import", workspaceFolder]); diff --git a/src/extension.ts b/src/extension.ts index 901c0c40e..e15bbfbf3 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -1,7 +1,7 @@ import * as fs from "node:fs"; import * as path from "node:path"; import * as vscode from "vscode"; -import { attemptSettingsUpdate, get_extension_uri, clean_godot_path } from "./utils"; +import { attemptSettingsUpdate, get_extension_uri, get_editor_path } from "./utils"; import { GDInlayHintsProvider, GDHoverProvider, @@ -93,8 +93,8 @@ async function initial_setup() { return; } const settingName = `editorPath.godot${projectVersion[0]}`; - const result = verify_godot_version(get_configuration(settingName), projectVersion[0]); - const godotPath = result.godotPath; + const godotPath = get_editor_path(projectVersion[0]); + const result = verify_godot_version(godotPath, projectVersion[0]); switch (result.status) { case "SUCCESS": { @@ -157,8 +157,8 @@ async function open_workspace_with_editor() { const projectVersion = await get_project_version(); const settingName = `editorPath.godot${projectVersion[0]}`; - const result = verify_godot_version(get_configuration(settingName), projectVersion[0]); - const godotPath = result.godotPath; + const godotPath = get_editor_path(projectVersion[0]); + const result = verify_godot_version(godotPath, projectVersion[0]); switch (result.status) { case "SUCCESS": { @@ -240,8 +240,7 @@ async function get_godot_path(): Promise { if (projectVersion === undefined) { return undefined; } - const settingName = `editorPath.godot${projectVersion[0]}`; - return clean_godot_path(get_configuration(settingName)); + return get_editor_path(projectVersion[0]); } class GodotEditorTerminal implements vscode.Pseudoterminal { diff --git a/src/lsp/ClientConnectionManager.ts b/src/lsp/ClientConnectionManager.ts index 210019ee8..37b2c464a 100644 --- a/src/lsp/ClientConnectionManager.ts +++ b/src/lsp/ClientConnectionManager.ts @@ -3,6 +3,7 @@ import * as vscode from "vscode"; import { createLogger, get_configuration, + get_editor_path, get_free_port, get_project_dir, get_project_version, @@ -116,10 +117,8 @@ export class ClientConnectionManager { targetVersion = "4.2"; } const settingName = `editorPath.godot${projectVersion[0]}`; - let godotPath = get_configuration(settingName); - + const godotPath = get_editor_path(projectVersion[0]); const result = verify_godot_version(godotPath, projectVersion[0]); - godotPath = result.godotPath; switch (result.status) { case "WRONG_VERSION": { diff --git a/src/utils/godot_utils.ts b/src/utils/godot_utils.ts index 371e17a3b..da2004129 100644 --- a/src/utils/godot_utils.ts +++ b/src/utils/godot_utils.ts @@ -3,6 +3,7 @@ import * as path from "node:path"; import * as fs from "node:fs"; import * as os from "node:os"; import { execSync } from "node:child_process"; +import { get_configuration } from "./vscode_utils"; export function get_editor_data_dir(): string { // from: https://stackoverflow.com/a/26227660 @@ -193,60 +194,100 @@ export async function convert_uid_to_uri(uid: string): Promise= 2) { - pathToClean = process.env[match[1]]; - } + godotPath = godotPath.replaceAll(/\$\{env:(.+?)\}/g, (_, key) => { + return process.env[key] || ""; + }); // strip leading and trailing quotes - let target = pathToClean.replace(/^"/, "").replace(/"$/, ""); + godotPath = godotPath.replace(/^"/, "").replace(/"$/, ""); // try to fix macos paths - if (os.platform() === "darwin" && target.endsWith(".app")) { - target = path.join(target, "Contents", "MacOS", "Godot"); + if (os.platform() === "darwin" && godotPath.endsWith(".app")) { + godotPath = path.join(godotPath, "Contents", "MacOS", "Godot"); + } + + // convert any relative path to absolute using the workspace dir + if (!path.isAbsolute(godotPath) && vscode.workspace.workspaceFolders && vscode.workspace.workspaceFolders.length > 0) { + const workspaceDir = vscode.workspace.workspaceFolders[0].uri.fsPath; + godotPath = path.join(workspaceDir, godotPath); } - return target; + return godotPath; } From fad41c994f49aa1ac78b0f90190c0075058d25ca Mon Sep 17 00:00:00 2001 From: David Nikdel <556630+ogapo@users.noreply.github.com> Date: Sun, 17 Aug 2025 07:49:51 -0400 Subject: [PATCH 2/2] fix for unit tests --- src/utils/godot_utils.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/utils/godot_utils.ts b/src/utils/godot_utils.ts index da2004129..38e266c2f 100644 --- a/src/utils/godot_utils.ts +++ b/src/utils/godot_utils.ts @@ -284,7 +284,9 @@ export function clean_godot_path(godotPath: string): string { } // convert any relative path to absolute using the workspace dir - if (!path.isAbsolute(godotPath) && vscode.workspace.workspaceFolders && vscode.workspace.workspaceFolders.length > 0) { + // not using path.isAbsolute here because the default "godot" may be an executable in the PATH + if ((godotPath.startsWith("./") || godotPath.startsWith("../") || godotPath.startsWith(".\\") || godotPath.startsWith("..\\")) + && vscode.workspace.workspaceFolders && vscode.workspace.workspaceFolders.length > 0) { const workspaceDir = vscode.workspace.workspaceFolders[0].uri.fsPath; godotPath = path.join(workspaceDir, godotPath); }