Skip to content

Commit

Permalink
Use virtualenv for VS Code language server (#48)
Browse files Browse the repository at this point in the history
  • Loading branch information
dinvlad authored Apr 23, 2024
1 parent 51b44f7 commit 28d8509
Showing 1 changed file with 40 additions and 53 deletions.
93 changes: 40 additions & 53 deletions client/vscode/src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,52 +19,32 @@
"use strict";

import { execFile } from "child_process";
import * as net from "net";
import * as fs from "fs";
import * as path from "path";
import { promisify } from "util";
import { ExtensionContext, workspace } from "vscode";
import { ExtensionContext, window, workspace } from "vscode";
import { LanguageClient, LanguageClientOptions, ServerOptions } from "vscode-languageclient/node";

const version: string = require("../package.json").version;

const language = "wdl";

let client: LanguageClient;
const log = window.createOutputChannel("WDL Language Server");

const version: string = require("../package.json").version;
log.appendLine(`WDL Language Server version: ${version}`);

function getClientOptions(): LanguageClientOptions {
return {
// Register the server for WDL documents
documentSelector: [
{ scheme: "file", language },
],
outputChannelName: "WDL Language Server",
outputChannel: log,
synchronize: {
// Notify the server about changes to .wdl files contained in the workspace
fileEvents: workspace.createFileSystemWatcher("**/*.wdl"),
},
};
}

function isStartedInDebugMode(): boolean {
return process.env.VSCODE_DEBUG_MODE === "true";
}

function startLangServerTCP(addr: number): LanguageClient {
const serverOptions: ServerOptions = () => {
return new Promise((resolve, reject) => {
const clientSocket = new net.Socket();
clientSocket.connect(addr, "127.0.0.1", () => {
resolve({
reader: clientSocket,
writer: clientSocket,
});
});
});
};

return new LanguageClient(language, serverOptions, getClientOptions());
}

function startLangServer(
command: string, args: string[], cwd: string,
): LanguageClient {
Expand All @@ -77,37 +57,44 @@ function startLangServer(
return new LanguageClient(language, serverOptions, getClientOptions());
}

export async function activate(context: ExtensionContext) {
if (isStartedInDebugMode()) {
// Development - Run the server manually
client = startLangServerTCP(2087);
} else {
// Production - Client is going to run the server (for use within `.vsix` package)
const cwd = path.join(__dirname, "../");
const pythonPath = workspace.getConfiguration(language).get<string>("pythonPath");
async function exec(cmd: string, ...args: string[]) {
return new Promise<void>(resolve => {
execFile(cmd, args, (err, stdout, stderr) => {
log.appendLine(`${cmd} ${args.join(" ")}`);
if (err) {
log.appendLine(err.message);
}
log.appendLine(stdout);
log.appendLine(stderr);
if (err) {
log.show();
}
resolve();
});
});
}

if (!pythonPath) {
throw new Error(`${language}.pythonPath is not set`);
}
let client: LanguageClient;

try {
const { stdout } = await promisify(execFile)(pythonPath, ["-m", "pip", "show", "wdl-lsp"]).catch(err => {
console.log(err);
return { stdout: "" };
});
const versionStr = stdout.split('\n').find(line => line.startsWith('Version:'));
if (!versionStr || versionStr.split(':')[1].trim() !== version) {
await promisify(execFile)(pythonPath, [
"-m", "pip", "install", "--user", "wdl-lsp==" + version,
]);
}
} catch (e) {
console.error(e);
}
export async function activate(context: ExtensionContext) {
const cwd = path.join(__dirname, "../");

client = startLangServer(pythonPath, ["-m", "wdl_lsp"], cwd);
const venvPath = path.join(__dirname, '.venv');
if (!fs.existsSync(venvPath)) {
const pythonPath = workspace.getConfiguration(language).get<string>("pythonPath")!;
await exec(pythonPath, "-m", "venv", venvPath);
}

const installArgs: string[] = [];
if (process.env.VSCODE_DEBUG_MODE === "true") {
installArgs.push(path.join(__dirname, '..', '..', '..', 'server'));
} else {
installArgs.push("--upgrade", "wdl-lsp");
}
const pythonPath = path.join(venvPath, 'bin', 'python');
await exec(pythonPath, "-m", "pip", "install", ...installArgs);

client = startLangServer(pythonPath, ["-m", "wdl_lsp"], cwd);
client.registerProposedFeatures();
await client.start();
}
Expand Down

0 comments on commit 28d8509

Please # to comment.