Skip to content

Commit

Permalink
automatically download language server in prod
Browse files Browse the repository at this point in the history
  • Loading branch information
chrehall68 committed Nov 11, 2024
1 parent f65e9c1 commit 0e5037d
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 8 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@ bun.lockb
out/
dist/
client/LICENSE
client/README.md
client/README.md
*.vsix
66 changes: 59 additions & 7 deletions client/src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,73 @@
* ------------------------------------------------------------------------------------------ */

import { ExtensionContext, ExtensionMode, workspace } from "vscode";
import { resolve } from "path";

import { createWriteStream, existsSync } from "fs";
import { chmod, mkdir } from "fs/promises";
import * as net from "net";
import { Readable } from "stream";
import { finished } from "stream/promises";
import {
LanguageClient,
LanguageClientOptions,
ServerOptions,
StreamInfo,
} from "vscode-languageclient/node";
import * as net from 'net';

let client: LanguageClient;

function getServerOptions(ctx: ExtensionContext): ServerOptions {
async function downloadToBin(
ctx: ExtensionContext,
url: string,
filename: string
) {
const res = await fetch(url);
if (!existsSync(ctx.asAbsolutePath("bin"))) {
await mkdir(ctx.asAbsolutePath("bin"), { recursive: true });
}
const actualFileName = ctx.asAbsolutePath(`bin/${filename}`);
const fileStream = createWriteStream(actualFileName, { flags: "wx" });
await finished(Readable.fromWeb(res.body).pipe(fileStream));
}

async function resolveServerExecutable(ctx: ExtensionContext): Promise<string> {
const platformDetails = {
win32: {
url: "https://github.com/chrehall68/vls/releases/download/1.0.0/vls-windows-amd64.exe",
filename: "vls.exe",
doChmod: false,
},
darwin: {
url: "https://github.com/chrehall68/vls/releases/download/1.0.0/vls-macos-amd64",
filename: "vls",
doChmod: true,
},
linux: {
url: "https://github.com/chrehall68/vls/releases/download/1.0.0/vls-linux-amd64",
filename: "vls",
doChmod: true,
},
};

const platform = process.platform;
if (!platformDetails[platform]) {
throw new Error(`Unsupported platform: ${platform}`);
}
const { url, filename, doChmod } = platformDetails[platform];
if (!existsSync(ctx.asAbsolutePath(`bin/${filename}`))) {
await downloadToBin(ctx, url, filename);
if (doChmod) {
// make it executable; rx-rx-rx
await chmod(ctx.asAbsolutePath(`bin/${filename}`), 0o555);
}
}
return ctx.asAbsolutePath(`bin/${filename}`);
}

async function getServerOptions(ctx: ExtensionContext): Promise<ServerOptions> {
if (ctx.extensionMode == ExtensionMode.Development) {
// In debug mode, the server is launched by VSCode (on this project) with Go debugger
// We need to connect to it with a socket because it's not a child process, no easy way to get its stdin/stdout (on linux, reading /proc/<pid>/0 and 1 is doable, but that's not cross platform)
// We need to connect to it with a socket because it's not a child process, no easy way to get its stdin/stdout (on linux, reading /proc/<pid>/0 and 1 is doable, but that's not cross platform)
const connectionInfo = {
host: "localhost",
port: 60256,
Expand All @@ -33,14 +84,15 @@ function getServerOptions(ctx: ExtensionContext): ServerOptions {
};
}

const executable = await resolveServerExecutable(ctx);
return {
command: resolve(ctx.extensionPath, "server", "vls"),
command: executable,
args: [],
};
}

export function activate(ctx: ExtensionContext) {
const serverOptions = getServerOptions(ctx);
export async function activate(ctx: ExtensionContext) {
const serverOptions = await getServerOptions(ctx);

// Options to control the language client
const clientOptions: LanguageClientOptions = {
Expand Down

0 comments on commit 0e5037d

Please sign in to comment.