From 7e36d73308525a4e0c419e6ca841dff6f76b46da Mon Sep 17 00:00:00 2001 From: Max Muoto Date: Sun, 2 Feb 2025 21:10:30 -0600 Subject: [PATCH 1/2] feat: Support custom file Path --- package.json | 6 ++++++ src/common/server.ts | 40 ++++++++++++++++++++++++++++++++++++++++ src/common/settings.ts | 3 +++ src/common/utilities.ts | 1 + src/common/version.ts | 33 +++++++++++++++++++++++++++++++++ 5 files changed, 83 insertions(+) create mode 100644 src/common/version.ts diff --git a/package.json b/package.json index 1e55ef0..e05a479 100644 --- a/package.json +++ b/package.json @@ -90,6 +90,12 @@ "type": "string" }, "type": "array" + }, + "tach.configuration": { + "default": "", + "description": "Path to a `tach.toml` file to use for configuration. By default, the extension will mirror the behavior that the `tach` CLI would have.", + "scope": "resource", + "type": "string" } } }, diff --git a/src/common/server.ts b/src/common/server.ts index e42e511..4108b18 100644 --- a/src/common/server.ts +++ b/src/common/server.ts @@ -14,9 +14,37 @@ import { traceError, traceInfo, traceVerbose } from './log/logging'; import { getExtensionSettings, getGlobalSettings, getWorkspaceSettings, ISettings } from './settings'; import { getLSClientTraceLevel, getProjectRoot } from './utilities'; import { isVirtualWorkspace } from './vscodeapi'; +import { execFile } from 'child_process'; +import { supportsCustomConfig, VersionInfo } from './version'; export type IInitOptions = { settings: ISettings[]; globalSettings: ISettings }; + +/** + * Executes a command for the given executable and returns the stdout output. + */ +function executeTachBinary(file: string, args: string[] = []): Promise { + return new Promise((resolve, reject) => { + execFile(file, args, (error, stdout, stderr) => { + if (error) { + reject(new Error(stderr || error.message)); + } else { + resolve(stdout); + } + }); + }); +} + +/** + * Gets the version information from the Tach executable. + */ +async function getTachVersion(pythonExecutable: string): Promise { + const stdout = await executeTachBinary(pythonExecutable, ["-m", "tach", "--version"]); + const version = stdout.trim().split(" ")[1]; + const [major, minor, patch] = version.split(".").map((x) => parseInt(x, 10)); + return new VersionInfo(major, minor, patch); + } + async function createServer( settings: ISettings, serverId: string, @@ -34,7 +62,19 @@ async function createServer( newEnv.PYTHONPATH = BUNDLED_PYTHON_LIBS_DIR; } + const args = settings.interpreter.slice(1).concat(["-m", "tach", "server"]); + + if (settings.configuration) { + const version = await getTachVersion(command); + if (!supportsCustomConfig(version)) { + traceError(`Server: Tach version ${version.toString()} does not support custom configuration files.`); + } else { + traceInfo(`Server: Using custom configuration file: ${settings.configuration}`); + args.push("-c", settings.configuration); + } + } + traceInfo(`Server run command: ${[command, ...args].join(' ')}`); const serverOptions: ServerOptions = { diff --git a/src/common/settings.ts b/src/common/settings.ts index ffada96..bb9ecf1 100644 --- a/src/common/settings.ts +++ b/src/common/settings.ts @@ -12,6 +12,7 @@ export interface ISettings { workspace: string; interpreter: string[]; importStrategy: ImportStrategy; + configuration: string | null; } export function getExtensionSettings(namespace: string, includeInterpreter?: boolean): Promise { @@ -65,6 +66,7 @@ export async function getWorkspaceSettings( workspace: workspace.uri.toString(), interpreter: resolveVariables(interpreter, workspace), importStrategy: config.get(`importStrategy`) ?? 'useBundled', + configuration: config.get(`configuration`) ?? null, }; return workspaceSetting; } @@ -90,6 +92,7 @@ export async function getGlobalSettings(namespace: string, includeInterpreter?: workspace: process.cwd(), interpreter: interpreter, importStrategy: getGlobalValue(config, 'importStrategy', 'useBundled'), + configuration: getGlobalValue(config, 'configuration', null), }; return setting; } diff --git a/src/common/utilities.ts b/src/common/utilities.ts index 22b1409..0dafd7b 100644 --- a/src/common/utilities.ts +++ b/src/common/utilities.ts @@ -6,6 +6,7 @@ import * as path from 'path'; import { LogLevel, Uri, WorkspaceFolder } from 'vscode'; import { Trace } from 'vscode-jsonrpc/node'; import { getWorkspaceFolders } from './vscodeapi'; +import { LanguageClient } from 'vscode-languageclient/node'; function logLevelToTrace(logLevel: LogLevel): Trace { switch (logLevel) { diff --git a/src/common/version.ts b/src/common/version.ts new file mode 100644 index 0000000..bd47c50 --- /dev/null +++ b/src/common/version.ts @@ -0,0 +1,33 @@ +export class VersionInfo { + constructor( + public major: number, + public minor: number, + public patch: number + ) {} + + toString(): string { + return `${this.major}.${this.minor}.${this.patch}`; + } +} + +function versionGte(a: VersionInfo, b: VersionInfo): boolean { + if (a.major !== b.major) { + return a.major > b.major; + } + if (a.minor !== b.minor) { + return a.minor > b.minor; + } + return a.patch >= b.patch; +} + +const MIN_VERSION_WITH_CONFIG = { + major: 0, + minor: 24, + patch: 0, +}; + + + +export function supportsCustomConfig(version: VersionInfo): boolean { + return versionGte(version, MIN_VERSION_WITH_CONFIG); +} From 7c93b6159198359b0f2622e502d5d53e332f9baa Mon Sep 17 00:00:00 2001 From: Max Muoto Date: Sun, 2 Feb 2025 21:12:06 -0600 Subject: [PATCH 2/2] Tweaks --- src/common/server.ts | 13 +++---------- src/common/utilities.ts | 1 - 2 files changed, 3 insertions(+), 11 deletions(-) diff --git a/src/common/server.ts b/src/common/server.ts index 4108b18..20e1d19 100644 --- a/src/common/server.ts +++ b/src/common/server.ts @@ -19,11 +19,7 @@ import { supportsCustomConfig, VersionInfo } from './version'; export type IInitOptions = { settings: ISettings[]; globalSettings: ISettings }; - -/** - * Executes a command for the given executable and returns the stdout output. - */ -function executeTachBinary(file: string, args: string[] = []): Promise { +function executeCommand(file: string, args: string[] = []): Promise { return new Promise((resolve, reject) => { execFile(file, args, (error, stdout, stderr) => { if (error) { @@ -34,12 +30,9 @@ function executeTachBinary(file: string, args: string[] = []): Promise { }); }); } - -/** - * Gets the version information from the Tach executable. - */ + async function getTachVersion(pythonExecutable: string): Promise { - const stdout = await executeTachBinary(pythonExecutable, ["-m", "tach", "--version"]); + const stdout = await executeCommand(pythonExecutable, ["-m", "tach", "--version"]); const version = stdout.trim().split(" ")[1]; const [major, minor, patch] = version.split(".").map((x) => parseInt(x, 10)); return new VersionInfo(major, minor, patch); diff --git a/src/common/utilities.ts b/src/common/utilities.ts index 0dafd7b..22b1409 100644 --- a/src/common/utilities.ts +++ b/src/common/utilities.ts @@ -6,7 +6,6 @@ import * as path from 'path'; import { LogLevel, Uri, WorkspaceFolder } from 'vscode'; import { Trace } from 'vscode-jsonrpc/node'; import { getWorkspaceFolders } from './vscodeapi'; -import { LanguageClient } from 'vscode-languageclient/node'; function logLevelToTrace(logLevel: LogLevel): Trace { switch (logLevel) {