From 22c743717a21bed54e6859d08e93f8d012cfdbf7 Mon Sep 17 00:00:00 2001 From: Raul Santos Date: Fri, 23 Jul 2021 22:42:16 +0200 Subject: [PATCH] Try to find the Godot executable Tries to find the Godot executable to set it in the generated `tasks.json` and `launch.json` files automatically for the user. The user can specify a custom path in the configuration to use as the Godot executable path, since it's unlikely we'll find it otherwise. --- package.json | 11 +++++++++++ src/assets-generator/debug.ts | 21 ++++++++++++--------- src/assets-generator/tasks.ts | 13 ++++++++----- src/configuration.ts | 6 +++++- src/debug-provider.ts | 4 +++- src/extension.ts | 2 +- src/godot-utils.ts | 31 +++++++++++++++++++++++++++++++ 7 files changed, 71 insertions(+), 17 deletions(-) diff --git a/package.json b/package.json index 2193775..427ff34 100644 --- a/package.json +++ b/package.json @@ -39,6 +39,7 @@ "chokidar": "^3.4.0", "fs-extra": "^10.0.0", "jsonc-parser": "^3.0.0", + "lookpath": "^1.2.1", "promise-socket": "^6.0.3", "vscode-debugprotocol": "^1.40.0" }, @@ -71,6 +72,16 @@ } ], "contributes": { + "configuration": { + "title": "Godot Mono", + "properties": { + "godot.csharp.executablePath": { + "type": "string", + "default": null, + "description": "Path to the Godot engine executable." + } + } + }, "commands": [ { "command": "godot.csharp.generateAssets", diff --git a/src/assets-generator/debug.ts b/src/assets-generator/debug.ts index a3e9387..bd3e521 100644 --- a/src/assets-generator/debug.ts +++ b/src/assets-generator/debug.ts @@ -2,19 +2,20 @@ import * as vscode from 'vscode'; import * as jsonc from 'jsonc-parser'; import * as fs from 'fs-extra'; import {getFormattingOptions, replaceCommentPropertiesWithComments, updateJsonWithComments} from '../json-utils'; +import {findGodotExecutablePath} from '../godot-utils'; -export function createLaunchConfiguration(): +export function createLaunchConfiguration(godotExecutablePath: string | undefined): {version: string, configurations: vscode.DebugConfiguration[]} { return { version: '2.0.0', - configurations: _createDebugConfigurations(), + configurations: _createDebugConfigurations(godotExecutablePath), }; } -export function createDebugConfigurationsArray(): vscode.DebugConfiguration[] +export function createDebugConfigurationsArray(godotExecutablePath: string | undefined): vscode.DebugConfiguration[] { - const configurations = _createDebugConfigurations(); + const configurations = _createDebugConfigurations(godotExecutablePath); // Remove comments configurations.forEach(configuration => { @@ -33,11 +34,11 @@ export function createDebugConfigurationsArray(): vscode.DebugConfiguration[] return configurations; } -function _createDebugConfigurations(): vscode.DebugConfiguration[] +function _createDebugConfigurations(godotExecutablePath: string | undefined): vscode.DebugConfiguration[] { return [ createPlayInEditorDebugConfiguration(), - createLaunchDebugConfiguration(), + createLaunchDebugConfiguration(godotExecutablePath), createAttachDebugConfiguration(), ]; } @@ -52,15 +53,16 @@ export function createPlayInEditorDebugConfiguration(): vscode.DebugConfiguratio }; } -export function createLaunchDebugConfiguration(): vscode.DebugConfiguration +export function createLaunchDebugConfiguration(godotExecutablePath: string | undefined): vscode.DebugConfiguration { + godotExecutablePath = godotExecutablePath ?? ''; return { name: 'Launch', type: 'godot-mono', request: 'launch', mode: 'executable', preLaunchTask: 'build', - executable: '', + executable: godotExecutablePath, 'OS-COMMENT1': 'See which arguments are available here:', 'OS-COMMENT2': 'https://docs.godotengine.org/en/stable/getting_started/editor/command_line_tutorial.html', executableArguments: [ @@ -83,7 +85,8 @@ export function createAttachDebugConfiguration() export async function addLaunchJsonIfNecessary(launchJsonPath: string): Promise { - const launchConfiguration = createLaunchConfiguration(); + const godotExecutablePath = await findGodotExecutablePath(); + const launchConfiguration = createLaunchConfiguration(godotExecutablePath); const formattingOptions = getFormattingOptions(); diff --git a/src/assets-generator/tasks.ts b/src/assets-generator/tasks.ts index a6e179d..617ad49 100644 --- a/src/assets-generator/tasks.ts +++ b/src/assets-generator/tasks.ts @@ -2,20 +2,22 @@ import * as tasks from 'vscode-tasks'; import * as jsonc from 'jsonc-parser'; import * as fs from 'fs-extra'; import {getFormattingOptions, replaceCommentPropertiesWithComments, updateJsonWithComments} from '../json-utils'; +import {findGodotExecutablePath} from '../godot-utils'; -export function createTasksConfiguration(): tasks.TaskConfiguration +export function createTasksConfiguration(godotExecutablePath: string | undefined): tasks.TaskConfiguration { return { version: '2.0.0', - tasks: [createBuildTaskDescription()], + tasks: [createBuildTaskDescription(godotExecutablePath)], }; } -export function createBuildTaskDescription(): tasks.TaskDescription +export function createBuildTaskDescription(godotExecutablePath: string | undefined): tasks.TaskDescription { + godotExecutablePath = godotExecutablePath ?? ''; return { label: 'build', - command: '', + command: godotExecutablePath, type: 'process', args: ['--build-solutions', '--path', '${workspaceRoot}', '--no-window', '-q'], problemMatcher: '$msCompile', @@ -24,7 +26,8 @@ export function createBuildTaskDescription(): tasks.TaskDescription export async function addTasksJsonIfNecessary(tasksJsonPath: string): Promise { - const tasksConfiguration = createTasksConfiguration(); + const godotExecutablePath = await findGodotExecutablePath(); + const tasksConfiguration = createTasksConfiguration(godotExecutablePath); const formattingOptions = getFormattingOptions(); diff --git a/src/configuration.ts b/src/configuration.ts index 884905b..5a48cc7 100644 --- a/src/configuration.ts +++ b/src/configuration.ts @@ -21,6 +21,8 @@ const DEFAULT_EXCEPTIONS: ExceptionConfigurations = { export class Configuration { public static Value: Configuration = new Configuration(); + public godotExecutablePath: string | undefined; + public exceptionOptions: ExceptionConfigurations = DEFAULT_EXCEPTIONS; public get exceptionOptionsForDebug(): DebugProtocol.ExceptionOptions[] { @@ -30,7 +32,7 @@ export class Configuration { private constructor(){ this.read(); vscode.workspace.onDidChangeConfiguration(e => { - if (e.affectsConfiguration('mono-debug')) + if (e.affectsConfiguration('godot.csharp') || e.affectsConfiguration('mono-debug')) { this.read(); } @@ -39,9 +41,11 @@ export class Configuration { public read() { + const godotConfiguration = vscode.workspace.getConfiguration('godot.csharp'); // Too lazy so we're re-using mono-debug extension settings for now... const monoConfiguration = vscode.workspace.getConfiguration('mono-debug'); + this.godotExecutablePath = godotConfiguration.get('executablePath'); this.exceptionOptions = monoConfiguration.get('exceptionOptions', DEFAULT_EXCEPTIONS); } diff --git a/src/debug-provider.ts b/src/debug-provider.ts index 8b28a01..0cb8820 100644 --- a/src/debug-provider.ts +++ b/src/debug-provider.ts @@ -3,6 +3,7 @@ import * as fs from 'fs-extra'; import {getVscodeFolder} from './vscode-utils'; import {Configuration} from './configuration'; import {AssetsGenerator, createDebugConfigurationsArray} from './assets-generator'; +import {findGodotExecutablePath} from './godot-utils'; export class GodotMonoDebugConfigProvider implements vscode.DebugConfigurationProvider { private godotProjectPath: string; @@ -31,7 +32,8 @@ export class GodotMonoDebugConfigProvider implements vscode.DebugConfigurationPr // Add a tasks.json await generator.addTasksJsonIfNecessary(); - return createDebugConfigurationsArray(); + const godotPath = await findGodotExecutablePath(); + return createDebugConfigurationsArray(godotPath); } public async resolveDebugConfiguration( diff --git a/src/extension.ts b/src/extension.ts index aea4ae0..f5d7798 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -6,7 +6,7 @@ import * as assets_provider from './assets-provider'; import { fixPathForGodot } from './godot-utils'; import { findProjectFiles, ProjectLocation, promptForProject } from './project-select'; -let client: Client; +export let client: Client; let codeCompletionProvider: vscode.Disposable; let debugConfigProvider: vscode.Disposable; let statusBarItem: vscode.StatusBarItem; diff --git a/src/godot-utils.ts b/src/godot-utils.ts index b0f52a0..5ff5937 100644 --- a/src/godot-utils.ts +++ b/src/godot-utils.ts @@ -1,3 +1,6 @@ +import {lookpath} from 'lookpath'; +import {Configuration} from './configuration'; +import {client} from './extension'; export function fixPathForGodot(path: string): string { if (process.platform === "win32") { @@ -13,3 +16,31 @@ export function fixPathForGodot(path: string): string { return path; } + +export async function findGodotExecutablePath(): Promise +{ + let path: string | undefined; + + // If the user has set the path in the settings, use that value + path = Configuration.Value.godotExecutablePath; + if (path) { + return path; + } + + // If the extension is connected to a running Godot editor instance, use its path + if (client !== undefined) { + path = client.metadata?.editorExecutablePath; + if (path) { + return path; + } + } + + // Check if the godot command is in the path + path = await lookpath('godot'); + if (path) { + return path; + } + + // We couldn't find the Godot executable + return undefined; +}