155 lines
3.7 KiB
TypeScript
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
|
|
}
|
|
}
|
|
|