openquest-vscode/client/src/server_binary.ts

155 lines
3.7 KiB
TypeScript

// Local Imports
import constants = require('./constants');
import { outputChannel } from './extension';
// External Imports
import * as path from 'path';
import { stat } from "fs/promises";
import * as vscode from "vscode";
/**
* Tries to find a language server executable in the following places:
* - $PATH or $HOME directory
* - The open project's VSCode workspace settings
* - Near the unicorns (joking, this one isn't real, just like the unicorns)
*/
export async function findLanguageServerPath(): Promise<string | undefined> {
let customPath = getCustomLanguageServerPath();
if (customPath !== undefined) { return customPath }
// TODO: Think if we should also prompt and do updates
if (promptInstallLanguageServerExecutable()) {
if (installLanguageServerExecutable()) {
return searchInstalledLanguageServer();
}
}
return undefined
}
/**
* Checks for a custom language server binary set in the Workspace or User settings
*/
function getCustomLanguageServerPath(): string | undefined {
const workspaceConfig = vscode.workspace.getConfiguration(constants.EXTENSION_NAME);
// Check for custom language server path
if (workspaceConfig.get("serverBinaryPath") && vscode.workspace.workspaceFolders !== undefined) {
outputChannel.appendLine(
path.resolve(
vscode.workspace.workspaceFolders[0].uri.fsPath,
workspaceConfig.get("serverBinaryPath") as string
)
);
return path.resolve(
vscode.workspace.workspaceFolders[0].uri.fsPath,
workspaceConfig.get("serverBinaryPath") as string
);
}
}
/**
* Prompt the user about installing the language server from a known origin
* and installs it if agreed
*/
async function promptInstallLanguageServerExecutable(): Promise<boolean> {
const choice = await vscode.window.showWarningMessage(
"Could not find a language server binary.\
Would you like to install one using `cargo install`?",
{},
"Yes"
);
// TODO: The prompt could also say what places we tried to look into
// and consequentially a better message on from where we are getting it
// and to where it is being installed
if (!choice) {
return false;
}
}
/**
* Download language server executable from mirrors defined in `package.json`
* and put them
* @returns
*/
async function installLanguageServerExecutable(): Promise<boolean> {
return false
}
/**
* Looks in known paths like HOME(Linux, Windows, Unix) and UserProfile(Windows)
*/
function searchInstalledLanguageServer() {
let base = process.env["HOME"];
if (process.platform === "win32") {
base = process.env["USERPROFILE"];
}
if (!base) {
return undefined
}
return undefined;
}
/**
* Looks for the cargo binary path in HOME
* @returns Path of the executables directory for cargo
*/
function lookForCargoBinPath() {
let base = process.env["HOME"];
if (!base) { return undefined}
const cargoInstallRoot = process.env["CARGO_INSTALL_ROOT"];
if (cargoInstallRoot) {
return cargoInstallRoot;
}
const cargoHome = process.env["CARGO_HOME"];
if (cargoHome) {
return path.join(cargoHome, "bin");
}
return path.join(base, ".cargo", "bin");
}
/**
* Gives language server binary name based on current environment
*/
function getBinaryName(): string {
switch (process.platform) {
case "win32":
return "openquest-ls.exe"
case "linux":
return "openquest-ls"
default:
return "openquest-ls"
}
}
/** Checks if a given path exists */
async function checkPathValidity(path: string): Promise<boolean> {
try {
await stat(path)
return true
} catch (_) {
return false
}
}