diff --git a/src/binaries/resolver.ts b/src/binaries/resolver.ts index 4ce66ec..cd723f4 100644 --- a/src/binaries/resolver.ts +++ b/src/binaries/resolver.ts @@ -9,6 +9,8 @@ import { BinaryConfig, BinaryInfo } from "./types"; export function resolveBinary(config: BinaryConfig, fallbackPath?: string): BinaryInfo { let path = vscode.workspace.getConfiguration("opa.dependency_paths").get(config.configKey); + let configuredOriginalPath: string | undefined; + if (path?.trim()) { const originalPath = path; path = replaceWorkspaceFolderPathVariable(path); @@ -27,6 +29,8 @@ export function resolveBinary(config: BinaryConfig, fallbackPath?: string): Bina ...(versionInfo.error && { error: versionInfo.error }), }; } + + configuredOriginalPath = originalPath; } const systemPath = fallbackPath || config.configKey; @@ -36,6 +40,10 @@ export function resolveBinary(config: BinaryConfig, fallbackPath?: string): Bina path: systemPath, source: "system", version: versionInfo.version, + ...(configuredOriginalPath && { + originalPath: configuredOriginalPath, + configuredPathMissing: true, + }), ...(versionInfo.error && { error: versionInfo.error }), }; } @@ -43,5 +51,35 @@ export function resolveBinary(config: BinaryConfig, fallbackPath?: string): Bina return { source: "missing", version: "missing", + ...(configuredOriginalPath && { + originalPath: configuredOriginalPath, + configuredPathMissing: true, + }), }; } + +// warnConfiguredPathMissing logs to the output channel and shows a popup +// indicating the configured binary path didn't exist on disk. Callers should +// gate this on binaryInfo.configuredPathMissing being set. +export function warnConfiguredPathMissing( + config: BinaryConfig, + binaryInfo: BinaryInfo, + outputChannel: vscode.OutputChannel, +): void { + const inspected = vscode.workspace + .getConfiguration("opa.dependency_paths") + .inspect(config.configKey); + const sourceDetail = inspected?.workspaceValue + ? "workspace settings (.vscode/settings.json)" + : "user settings"; + + outputChannel.appendLine( + `${config.name}: configured path '${binaryInfo.originalPath}' from ${sourceDetail} not found; falling back to ${ + binaryInfo.source === "system" ? "system PATH" : "no binary available" + }.`, + ); + + vscode.window.showWarningMessage( + `${config.name} binary not found at configured path '${binaryInfo.originalPath}' (from ${sourceDetail}).`, + ); +} diff --git a/src/binaries/types.ts b/src/binaries/types.ts index f6a9d2d..349f97b 100644 --- a/src/binaries/types.ts +++ b/src/binaries/types.ts @@ -18,6 +18,7 @@ export interface BinaryInfo { path?: string; source: "configured" | "system" | "missing"; originalPath?: string; + configuredPathMissing?: boolean; version: string; error?: string; } diff --git a/src/extension.ts b/src/extension.ts index 262da5f..72da6a2 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -4,7 +4,14 @@ import * as fs from "fs"; import * as path from "path"; import * as vscode from "vscode"; -import { BinaryConfig, installBinary, OPA_CONFIG, REGAL_CONFIG, resolveBinary } from "./binaries"; +import { + BinaryConfig, + installBinary, + OPA_CONFIG, + REGAL_CONFIG, + resolveBinary, + warnConfiguredPathMissing, +} from "./binaries"; import { activateDebugger } from "./da/activate"; import { activateRegal, @@ -144,6 +151,12 @@ export async function activate(context: vscode.ExtensionContext) { // check for missing binaries and prompt to install them checkMissingBinaries(); + // warn if the configured opa.dependency_paths.opa points to a non-existent file + const opaBinaryInfo = resolveBinary(OPA_CONFIG, "opa"); + if (opaBinaryInfo.configuredPathMissing) { + warnConfiguredPathMissing(OPA_CONFIG, opaBinaryInfo, opaOutputChannel); + } + // start Regal language server and wire up the client const result = await activateRegal(regalOptions); if (result) { diff --git a/src/ls/clients/regal.ts b/src/ls/clients/regal.ts index 5c13f98..225364b 100644 --- a/src/ls/clients/regal.ts +++ b/src/ls/clients/regal.ts @@ -13,7 +13,7 @@ import { ServerOptions, State, } from "vscode-languageclient/node"; -import { REGAL_CONFIG, resolveBinary } from "../../binaries"; +import { REGAL_CONFIG, resolveBinary, warnConfiguredPathMissing } from "../../binaries"; import { evalResultDecorationType, evalResultTargetSuccessDecorationType, @@ -155,6 +155,10 @@ export async function activateRegal( const binaryInfo = resolveBinary(REGAL_CONFIG, "regal"); + if (binaryInfo.configuredPathMissing) { + warnConfiguredPathMissing(REGAL_CONFIG, binaryInfo, opaOutputChannel); + } + // Validate binary availability if (!binaryInfo.path) { clientLock = false;